168d75effSDimitry Andric //===-- asan_rtl.cpp ------------------------------------------------------===// 268d75effSDimitry Andric // 368d75effSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 468d75effSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 568d75effSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 668d75effSDimitry Andric // 768d75effSDimitry Andric //===----------------------------------------------------------------------===// 868d75effSDimitry Andric // 968d75effSDimitry Andric // This file is a part of AddressSanitizer, an address sanity checker. 1068d75effSDimitry Andric // 1168d75effSDimitry Andric // Main file of the ASan run-time library. 1268d75effSDimitry Andric //===----------------------------------------------------------------------===// 1368d75effSDimitry Andric 1468d75effSDimitry Andric #include "asan_activation.h" 1568d75effSDimitry Andric #include "asan_allocator.h" 16fe6060f1SDimitry Andric #include "asan_fake_stack.h" 1768d75effSDimitry Andric #include "asan_interceptors.h" 1868d75effSDimitry Andric #include "asan_interface_internal.h" 1968d75effSDimitry Andric #include "asan_internal.h" 2068d75effSDimitry Andric #include "asan_mapping.h" 2168d75effSDimitry Andric #include "asan_poisoning.h" 2268d75effSDimitry Andric #include "asan_report.h" 2368d75effSDimitry Andric #include "asan_stack.h" 2468d75effSDimitry Andric #include "asan_stats.h" 2568d75effSDimitry Andric #include "asan_suppressions.h" 2668d75effSDimitry Andric #include "asan_thread.h" 27fe6060f1SDimitry Andric #include "lsan/lsan_common.h" 2868d75effSDimitry Andric #include "sanitizer_common/sanitizer_atomic.h" 2968d75effSDimitry Andric #include "sanitizer_common/sanitizer_flags.h" 3081ad6265SDimitry Andric #include "sanitizer_common/sanitizer_interface_internal.h" 3168d75effSDimitry Andric #include "sanitizer_common/sanitizer_libc.h" 3268d75effSDimitry Andric #include "sanitizer_common/sanitizer_symbolizer.h" 3368d75effSDimitry Andric #include "ubsan/ubsan_init.h" 3468d75effSDimitry Andric #include "ubsan/ubsan_platform.h" 3568d75effSDimitry Andric 3668d75effSDimitry Andric uptr __asan_shadow_memory_dynamic_address; // Global interface symbol. 3768d75effSDimitry Andric int __asan_option_detect_stack_use_after_return; // Global interface symbol. 3868d75effSDimitry Andric uptr *__asan_test_only_reported_buggy_pointer; // Used only for testing asan. 3968d75effSDimitry Andric 4068d75effSDimitry Andric namespace __asan { 4168d75effSDimitry Andric 4268d75effSDimitry Andric uptr AsanMappingProfile[kAsanMappingProfileSize]; 4368d75effSDimitry Andric 4468d75effSDimitry Andric static void AsanDie() { 4568d75effSDimitry Andric static atomic_uint32_t num_calls; 4668d75effSDimitry Andric if (atomic_fetch_add(&num_calls, 1, memory_order_relaxed) != 0) { 4768d75effSDimitry Andric // Don't die twice - run a busy loop. 4881ad6265SDimitry Andric while (1) { 4981ad6265SDimitry Andric internal_sched_yield(); 5081ad6265SDimitry Andric } 5168d75effSDimitry Andric } 52e8d8bef9SDimitry Andric if (common_flags()->print_module_map >= 1) 53e8d8bef9SDimitry Andric DumpProcessMap(); 5481ad6265SDimitry Andric 5581ad6265SDimitry Andric WaitForDebugger(flags()->sleep_before_dying, "before dying"); 5681ad6265SDimitry Andric 5768d75effSDimitry Andric if (flags()->unmap_shadow_on_exit) { 5868d75effSDimitry Andric if (kMidMemBeg) { 5968d75effSDimitry Andric UnmapOrDie((void*)kLowShadowBeg, kMidMemBeg - kLowShadowBeg); 6068d75effSDimitry Andric UnmapOrDie((void*)kMidMemEnd, kHighShadowEnd - kMidMemEnd); 6168d75effSDimitry Andric } else { 6268d75effSDimitry Andric if (kHighShadowEnd) 6368d75effSDimitry Andric UnmapOrDie((void*)kLowShadowBeg, kHighShadowEnd - kLowShadowBeg); 6468d75effSDimitry Andric } 6568d75effSDimitry Andric } 6668d75effSDimitry Andric } 6768d75effSDimitry Andric 68fe6060f1SDimitry Andric static void CheckUnwind() { 69fe6060f1SDimitry Andric GET_STACK_TRACE(kStackTraceMax, common_flags()->fast_unwind_on_check); 70fe6060f1SDimitry Andric stack.Print(); 7168d75effSDimitry Andric } 7268d75effSDimitry Andric 7368d75effSDimitry Andric // -------------------------- Globals --------------------- {{{1 745f757f3fSDimitry Andric static StaticSpinMutex asan_inited_mutex; 755f757f3fSDimitry Andric static atomic_uint8_t asan_inited = {0}; 765f757f3fSDimitry Andric 775f757f3fSDimitry Andric static void SetAsanInited() { 785f757f3fSDimitry Andric atomic_store(&asan_inited, 1, memory_order_release); 795f757f3fSDimitry Andric } 805f757f3fSDimitry Andric 815f757f3fSDimitry Andric bool AsanInited() { 825f757f3fSDimitry Andric return atomic_load(&asan_inited, memory_order_acquire) == 1; 835f757f3fSDimitry Andric } 845f757f3fSDimitry Andric 85bdd1243dSDimitry Andric bool replace_intrin_cached; 8668d75effSDimitry Andric 8768d75effSDimitry Andric #if !ASAN_FIXED_MAPPING 8868d75effSDimitry Andric uptr kHighMemEnd, kMidMemBeg, kMidMemEnd; 8968d75effSDimitry Andric #endif 9068d75effSDimitry Andric 9168d75effSDimitry Andric // -------------------------- Misc ---------------- {{{1 9268d75effSDimitry Andric void ShowStatsAndAbort() { 9368d75effSDimitry Andric __asan_print_accumulated_stats(); 9468d75effSDimitry Andric Die(); 9568d75effSDimitry Andric } 9668d75effSDimitry Andric 97fe6060f1SDimitry Andric NOINLINE 98fe6060f1SDimitry Andric static void ReportGenericErrorWrapper(uptr addr, bool is_write, int size, 99fe6060f1SDimitry Andric int exp_arg, bool fatal) { 100fe6060f1SDimitry Andric GET_CALLER_PC_BP_SP; 101fe6060f1SDimitry Andric ReportGenericError(pc, bp, sp, addr, is_write, size, exp_arg, fatal); 102fe6060f1SDimitry Andric } 103fe6060f1SDimitry Andric 10468d75effSDimitry Andric // --------------- LowLevelAllocateCallbac ---------- {{{1 10568d75effSDimitry Andric static void OnLowLevelAllocate(uptr ptr, uptr size) { 10668d75effSDimitry Andric PoisonShadow(ptr, size, kAsanInternalHeapMagic); 10768d75effSDimitry Andric } 10868d75effSDimitry Andric 10968d75effSDimitry Andric // -------------------------- Run-time entry ------------------- {{{1 11068d75effSDimitry Andric // exported functions 11168d75effSDimitry Andric #define ASAN_REPORT_ERROR(type, is_write, size) \ 11268d75effSDimitry Andric extern "C" NOINLINE INTERFACE_ATTRIBUTE \ 11368d75effSDimitry Andric void __asan_report_ ## type ## size(uptr addr) { \ 11468d75effSDimitry Andric GET_CALLER_PC_BP_SP; \ 11568d75effSDimitry Andric ReportGenericError(pc, bp, sp, addr, is_write, size, 0, true); \ 11668d75effSDimitry Andric } \ 11768d75effSDimitry Andric extern "C" NOINLINE INTERFACE_ATTRIBUTE \ 11868d75effSDimitry Andric void __asan_report_exp_ ## type ## size(uptr addr, u32 exp) { \ 11968d75effSDimitry Andric GET_CALLER_PC_BP_SP; \ 12068d75effSDimitry Andric ReportGenericError(pc, bp, sp, addr, is_write, size, exp, true); \ 12168d75effSDimitry Andric } \ 12268d75effSDimitry Andric extern "C" NOINLINE INTERFACE_ATTRIBUTE \ 12368d75effSDimitry Andric void __asan_report_ ## type ## size ## _noabort(uptr addr) { \ 12468d75effSDimitry Andric GET_CALLER_PC_BP_SP; \ 12568d75effSDimitry Andric ReportGenericError(pc, bp, sp, addr, is_write, size, 0, false); \ 12668d75effSDimitry Andric } \ 12768d75effSDimitry Andric 12868d75effSDimitry Andric ASAN_REPORT_ERROR(load, false, 1) 12968d75effSDimitry Andric ASAN_REPORT_ERROR(load, false, 2) 13068d75effSDimitry Andric ASAN_REPORT_ERROR(load, false, 4) 13168d75effSDimitry Andric ASAN_REPORT_ERROR(load, false, 8) 13268d75effSDimitry Andric ASAN_REPORT_ERROR(load, false, 16) 13368d75effSDimitry Andric ASAN_REPORT_ERROR(store, true, 1) 13468d75effSDimitry Andric ASAN_REPORT_ERROR(store, true, 2) 13568d75effSDimitry Andric ASAN_REPORT_ERROR(store, true, 4) 13668d75effSDimitry Andric ASAN_REPORT_ERROR(store, true, 8) 13768d75effSDimitry Andric ASAN_REPORT_ERROR(store, true, 16) 13868d75effSDimitry Andric 13968d75effSDimitry Andric #define ASAN_REPORT_ERROR_N(type, is_write) \ 14068d75effSDimitry Andric extern "C" NOINLINE INTERFACE_ATTRIBUTE \ 14168d75effSDimitry Andric void __asan_report_ ## type ## _n(uptr addr, uptr size) { \ 14268d75effSDimitry Andric GET_CALLER_PC_BP_SP; \ 14368d75effSDimitry Andric ReportGenericError(pc, bp, sp, addr, is_write, size, 0, true); \ 14468d75effSDimitry Andric } \ 14568d75effSDimitry Andric extern "C" NOINLINE INTERFACE_ATTRIBUTE \ 14668d75effSDimitry Andric void __asan_report_exp_ ## type ## _n(uptr addr, uptr size, u32 exp) { \ 14768d75effSDimitry Andric GET_CALLER_PC_BP_SP; \ 14868d75effSDimitry Andric ReportGenericError(pc, bp, sp, addr, is_write, size, exp, true); \ 14968d75effSDimitry Andric } \ 15068d75effSDimitry Andric extern "C" NOINLINE INTERFACE_ATTRIBUTE \ 15168d75effSDimitry Andric void __asan_report_ ## type ## _n_noabort(uptr addr, uptr size) { \ 15268d75effSDimitry Andric GET_CALLER_PC_BP_SP; \ 15368d75effSDimitry Andric ReportGenericError(pc, bp, sp, addr, is_write, size, 0, false); \ 15468d75effSDimitry Andric } \ 15568d75effSDimitry Andric 15668d75effSDimitry Andric ASAN_REPORT_ERROR_N(load, false) 15768d75effSDimitry Andric ASAN_REPORT_ERROR_N(store, true) 15868d75effSDimitry Andric 15968d75effSDimitry Andric #define ASAN_MEMORY_ACCESS_CALLBACK_BODY(type, is_write, size, exp_arg, fatal) \ 16068d75effSDimitry Andric uptr sp = MEM_TO_SHADOW(addr); \ 1610eae32dcSDimitry Andric uptr s = size <= ASAN_SHADOW_GRANULARITY ? *reinterpret_cast<u8 *>(sp) \ 16268d75effSDimitry Andric : *reinterpret_cast<u16 *>(sp); \ 16368d75effSDimitry Andric if (UNLIKELY(s)) { \ 1640eae32dcSDimitry Andric if (UNLIKELY(size >= ASAN_SHADOW_GRANULARITY || \ 1650eae32dcSDimitry Andric ((s8)((addr & (ASAN_SHADOW_GRANULARITY - 1)) + size - 1)) >= \ 16668d75effSDimitry Andric (s8)s)) { \ 167fe6060f1SDimitry Andric ReportGenericErrorWrapper(addr, is_write, size, exp_arg, fatal); \ 16868d75effSDimitry Andric } \ 16968d75effSDimitry Andric } 17068d75effSDimitry Andric 17168d75effSDimitry Andric #define ASAN_MEMORY_ACCESS_CALLBACK(type, is_write, size) \ 17268d75effSDimitry Andric extern "C" NOINLINE INTERFACE_ATTRIBUTE \ 17368d75effSDimitry Andric void __asan_##type##size(uptr addr) { \ 17468d75effSDimitry Andric ASAN_MEMORY_ACCESS_CALLBACK_BODY(type, is_write, size, 0, true) \ 17568d75effSDimitry Andric } \ 17668d75effSDimitry Andric extern "C" NOINLINE INTERFACE_ATTRIBUTE \ 17768d75effSDimitry Andric void __asan_exp_##type##size(uptr addr, u32 exp) { \ 17868d75effSDimitry Andric ASAN_MEMORY_ACCESS_CALLBACK_BODY(type, is_write, size, exp, true) \ 17968d75effSDimitry Andric } \ 18068d75effSDimitry Andric extern "C" NOINLINE INTERFACE_ATTRIBUTE \ 18168d75effSDimitry Andric void __asan_##type##size ## _noabort(uptr addr) { \ 18268d75effSDimitry Andric ASAN_MEMORY_ACCESS_CALLBACK_BODY(type, is_write, size, 0, false) \ 18368d75effSDimitry Andric } \ 18468d75effSDimitry Andric 18568d75effSDimitry Andric ASAN_MEMORY_ACCESS_CALLBACK(load, false, 1) 18668d75effSDimitry Andric ASAN_MEMORY_ACCESS_CALLBACK(load, false, 2) 18768d75effSDimitry Andric ASAN_MEMORY_ACCESS_CALLBACK(load, false, 4) 18868d75effSDimitry Andric ASAN_MEMORY_ACCESS_CALLBACK(load, false, 8) 18968d75effSDimitry Andric ASAN_MEMORY_ACCESS_CALLBACK(load, false, 16) 19068d75effSDimitry Andric ASAN_MEMORY_ACCESS_CALLBACK(store, true, 1) 19168d75effSDimitry Andric ASAN_MEMORY_ACCESS_CALLBACK(store, true, 2) 19268d75effSDimitry Andric ASAN_MEMORY_ACCESS_CALLBACK(store, true, 4) 19368d75effSDimitry Andric ASAN_MEMORY_ACCESS_CALLBACK(store, true, 8) 19468d75effSDimitry Andric ASAN_MEMORY_ACCESS_CALLBACK(store, true, 16) 19568d75effSDimitry Andric 19668d75effSDimitry Andric extern "C" 19768d75effSDimitry Andric NOINLINE INTERFACE_ATTRIBUTE 19868d75effSDimitry Andric void __asan_loadN(uptr addr, uptr size) { 19981ad6265SDimitry Andric if ((addr = __asan_region_is_poisoned(addr, size))) { 20068d75effSDimitry Andric GET_CALLER_PC_BP_SP; 20168d75effSDimitry Andric ReportGenericError(pc, bp, sp, addr, false, size, 0, true); 20268d75effSDimitry Andric } 20368d75effSDimitry Andric } 20468d75effSDimitry Andric 20568d75effSDimitry Andric extern "C" 20668d75effSDimitry Andric NOINLINE INTERFACE_ATTRIBUTE 20768d75effSDimitry Andric void __asan_exp_loadN(uptr addr, uptr size, u32 exp) { 20881ad6265SDimitry Andric if ((addr = __asan_region_is_poisoned(addr, size))) { 20968d75effSDimitry Andric GET_CALLER_PC_BP_SP; 21068d75effSDimitry Andric ReportGenericError(pc, bp, sp, addr, false, size, exp, true); 21168d75effSDimitry Andric } 21268d75effSDimitry Andric } 21368d75effSDimitry Andric 21468d75effSDimitry Andric extern "C" 21568d75effSDimitry Andric NOINLINE INTERFACE_ATTRIBUTE 21668d75effSDimitry Andric void __asan_loadN_noabort(uptr addr, uptr size) { 21781ad6265SDimitry Andric if ((addr = __asan_region_is_poisoned(addr, size))) { 21868d75effSDimitry Andric GET_CALLER_PC_BP_SP; 21968d75effSDimitry Andric ReportGenericError(pc, bp, sp, addr, false, size, 0, false); 22068d75effSDimitry Andric } 22168d75effSDimitry Andric } 22268d75effSDimitry Andric 22368d75effSDimitry Andric extern "C" 22468d75effSDimitry Andric NOINLINE INTERFACE_ATTRIBUTE 22568d75effSDimitry Andric void __asan_storeN(uptr addr, uptr size) { 22681ad6265SDimitry Andric if ((addr = __asan_region_is_poisoned(addr, size))) { 22768d75effSDimitry Andric GET_CALLER_PC_BP_SP; 22868d75effSDimitry Andric ReportGenericError(pc, bp, sp, addr, true, size, 0, true); 22968d75effSDimitry Andric } 23068d75effSDimitry Andric } 23168d75effSDimitry Andric 23268d75effSDimitry Andric extern "C" 23368d75effSDimitry Andric NOINLINE INTERFACE_ATTRIBUTE 23468d75effSDimitry Andric void __asan_exp_storeN(uptr addr, uptr size, u32 exp) { 23581ad6265SDimitry Andric if ((addr = __asan_region_is_poisoned(addr, size))) { 23668d75effSDimitry Andric GET_CALLER_PC_BP_SP; 23768d75effSDimitry Andric ReportGenericError(pc, bp, sp, addr, true, size, exp, true); 23868d75effSDimitry Andric } 23968d75effSDimitry Andric } 24068d75effSDimitry Andric 24168d75effSDimitry Andric extern "C" 24268d75effSDimitry Andric NOINLINE INTERFACE_ATTRIBUTE 24368d75effSDimitry Andric void __asan_storeN_noabort(uptr addr, uptr size) { 24481ad6265SDimitry Andric if ((addr = __asan_region_is_poisoned(addr, size))) { 24568d75effSDimitry Andric GET_CALLER_PC_BP_SP; 24668d75effSDimitry Andric ReportGenericError(pc, bp, sp, addr, true, size, 0, false); 24768d75effSDimitry Andric } 24868d75effSDimitry Andric } 24968d75effSDimitry Andric 25068d75effSDimitry Andric // Force the linker to keep the symbols for various ASan interface functions. 25168d75effSDimitry Andric // We want to keep those in the executable in order to let the instrumented 25268d75effSDimitry Andric // dynamic libraries access the symbol even if it is not used by the executable 25368d75effSDimitry Andric // itself. This should help if the build system is removing dead code at link 25468d75effSDimitry Andric // time. 25568d75effSDimitry Andric static NOINLINE void force_interface_symbols() { 25668d75effSDimitry Andric volatile int fake_condition = 0; // prevent dead condition elimination. 25768d75effSDimitry Andric // __asan_report_* functions are noreturn, so we need a switch to prevent 25868d75effSDimitry Andric // the compiler from removing any of them. 25968d75effSDimitry Andric // clang-format off 26068d75effSDimitry Andric switch (fake_condition) { 26168d75effSDimitry Andric case 1: __asan_report_load1(0); break; 26268d75effSDimitry Andric case 2: __asan_report_load2(0); break; 26368d75effSDimitry Andric case 3: __asan_report_load4(0); break; 26468d75effSDimitry Andric case 4: __asan_report_load8(0); break; 26568d75effSDimitry Andric case 5: __asan_report_load16(0); break; 26668d75effSDimitry Andric case 6: __asan_report_load_n(0, 0); break; 26768d75effSDimitry Andric case 7: __asan_report_store1(0); break; 26868d75effSDimitry Andric case 8: __asan_report_store2(0); break; 26968d75effSDimitry Andric case 9: __asan_report_store4(0); break; 27068d75effSDimitry Andric case 10: __asan_report_store8(0); break; 27168d75effSDimitry Andric case 11: __asan_report_store16(0); break; 27268d75effSDimitry Andric case 12: __asan_report_store_n(0, 0); break; 27368d75effSDimitry Andric case 13: __asan_report_exp_load1(0, 0); break; 27468d75effSDimitry Andric case 14: __asan_report_exp_load2(0, 0); break; 27568d75effSDimitry Andric case 15: __asan_report_exp_load4(0, 0); break; 27668d75effSDimitry Andric case 16: __asan_report_exp_load8(0, 0); break; 27768d75effSDimitry Andric case 17: __asan_report_exp_load16(0, 0); break; 27868d75effSDimitry Andric case 18: __asan_report_exp_load_n(0, 0, 0); break; 27968d75effSDimitry Andric case 19: __asan_report_exp_store1(0, 0); break; 28068d75effSDimitry Andric case 20: __asan_report_exp_store2(0, 0); break; 28168d75effSDimitry Andric case 21: __asan_report_exp_store4(0, 0); break; 28268d75effSDimitry Andric case 22: __asan_report_exp_store8(0, 0); break; 28368d75effSDimitry Andric case 23: __asan_report_exp_store16(0, 0); break; 28468d75effSDimitry Andric case 24: __asan_report_exp_store_n(0, 0, 0); break; 28568d75effSDimitry Andric case 25: __asan_register_globals(nullptr, 0); break; 28668d75effSDimitry Andric case 26: __asan_unregister_globals(nullptr, 0); break; 28768d75effSDimitry Andric case 27: __asan_set_death_callback(nullptr); break; 28868d75effSDimitry Andric case 28: __asan_set_error_report_callback(nullptr); break; 28968d75effSDimitry Andric case 29: __asan_handle_no_return(); break; 29068d75effSDimitry Andric case 30: __asan_address_is_poisoned(nullptr); break; 29168d75effSDimitry Andric case 31: __asan_poison_memory_region(nullptr, 0); break; 29268d75effSDimitry Andric case 32: __asan_unpoison_memory_region(nullptr, 0); break; 29368d75effSDimitry Andric case 34: __asan_before_dynamic_init(nullptr); break; 29468d75effSDimitry Andric case 35: __asan_after_dynamic_init(); break; 29568d75effSDimitry Andric case 36: __asan_poison_stack_memory(0, 0); break; 29668d75effSDimitry Andric case 37: __asan_unpoison_stack_memory(0, 0); break; 29768d75effSDimitry Andric case 38: __asan_region_is_poisoned(0, 0); break; 29868d75effSDimitry Andric case 39: __asan_describe_address(0); break; 29968d75effSDimitry Andric case 40: __asan_set_shadow_00(0, 0); break; 300bdd1243dSDimitry Andric case 41: __asan_set_shadow_01(0, 0); break; 301bdd1243dSDimitry Andric case 42: __asan_set_shadow_02(0, 0); break; 302bdd1243dSDimitry Andric case 43: __asan_set_shadow_03(0, 0); break; 303bdd1243dSDimitry Andric case 44: __asan_set_shadow_04(0, 0); break; 304bdd1243dSDimitry Andric case 45: __asan_set_shadow_05(0, 0); break; 305bdd1243dSDimitry Andric case 46: __asan_set_shadow_06(0, 0); break; 306bdd1243dSDimitry Andric case 47: __asan_set_shadow_07(0, 0); break; 307bdd1243dSDimitry Andric case 48: __asan_set_shadow_f1(0, 0); break; 308bdd1243dSDimitry Andric case 49: __asan_set_shadow_f2(0, 0); break; 309bdd1243dSDimitry Andric case 50: __asan_set_shadow_f3(0, 0); break; 310bdd1243dSDimitry Andric case 51: __asan_set_shadow_f5(0, 0); break; 311bdd1243dSDimitry Andric case 52: __asan_set_shadow_f8(0, 0); break; 31268d75effSDimitry Andric } 31368d75effSDimitry Andric // clang-format on 31468d75effSDimitry Andric } 31568d75effSDimitry Andric 31668d75effSDimitry Andric static void asan_atexit() { 31768d75effSDimitry Andric Printf("AddressSanitizer exit stats:\n"); 31868d75effSDimitry Andric __asan_print_accumulated_stats(); 31968d75effSDimitry Andric // Print AsanMappingProfile. 32068d75effSDimitry Andric for (uptr i = 0; i < kAsanMappingProfileSize; i++) { 32168d75effSDimitry Andric if (AsanMappingProfile[i] == 0) continue; 32268d75effSDimitry Andric Printf("asan_mapping.h:%zd -- %zd\n", i, AsanMappingProfile[i]); 32368d75effSDimitry Andric } 32468d75effSDimitry Andric } 32568d75effSDimitry Andric 32668d75effSDimitry Andric static void InitializeHighMemEnd() { 32768d75effSDimitry Andric #if !ASAN_FIXED_MAPPING 32868d75effSDimitry Andric kHighMemEnd = GetMaxUserVirtualAddress(); 32968d75effSDimitry Andric // Increase kHighMemEnd to make sure it's properly 33068d75effSDimitry Andric // aligned together with kHighMemBeg: 3310eae32dcSDimitry Andric kHighMemEnd |= (GetMmapGranularity() << ASAN_SHADOW_SCALE) - 1; 33268d75effSDimitry Andric #endif // !ASAN_FIXED_MAPPING 33368d75effSDimitry Andric CHECK_EQ((kHighMemBeg % GetMmapGranularity()), 0); 33468d75effSDimitry Andric } 33568d75effSDimitry Andric 33668d75effSDimitry Andric void PrintAddressSpaceLayout() { 33768d75effSDimitry Andric if (kHighMemBeg) { 33868d75effSDimitry Andric Printf("|| `[%p, %p]` || HighMem ||\n", 33968d75effSDimitry Andric (void*)kHighMemBeg, (void*)kHighMemEnd); 34068d75effSDimitry Andric Printf("|| `[%p, %p]` || HighShadow ||\n", 34168d75effSDimitry Andric (void*)kHighShadowBeg, (void*)kHighShadowEnd); 34268d75effSDimitry Andric } 34368d75effSDimitry Andric if (kMidMemBeg) { 34468d75effSDimitry Andric Printf("|| `[%p, %p]` || ShadowGap3 ||\n", 34568d75effSDimitry Andric (void*)kShadowGap3Beg, (void*)kShadowGap3End); 34668d75effSDimitry Andric Printf("|| `[%p, %p]` || MidMem ||\n", 34768d75effSDimitry Andric (void*)kMidMemBeg, (void*)kMidMemEnd); 34868d75effSDimitry Andric Printf("|| `[%p, %p]` || ShadowGap2 ||\n", 34968d75effSDimitry Andric (void*)kShadowGap2Beg, (void*)kShadowGap2End); 35068d75effSDimitry Andric Printf("|| `[%p, %p]` || MidShadow ||\n", 35168d75effSDimitry Andric (void*)kMidShadowBeg, (void*)kMidShadowEnd); 35268d75effSDimitry Andric } 35368d75effSDimitry Andric Printf("|| `[%p, %p]` || ShadowGap ||\n", 35468d75effSDimitry Andric (void*)kShadowGapBeg, (void*)kShadowGapEnd); 35568d75effSDimitry Andric if (kLowShadowBeg) { 35668d75effSDimitry Andric Printf("|| `[%p, %p]` || LowShadow ||\n", 35768d75effSDimitry Andric (void*)kLowShadowBeg, (void*)kLowShadowEnd); 35868d75effSDimitry Andric Printf("|| `[%p, %p]` || LowMem ||\n", 35968d75effSDimitry Andric (void*)kLowMemBeg, (void*)kLowMemEnd); 36068d75effSDimitry Andric } 36168d75effSDimitry Andric Printf("MemToShadow(shadow): %p %p", 36268d75effSDimitry Andric (void*)MEM_TO_SHADOW(kLowShadowBeg), 36368d75effSDimitry Andric (void*)MEM_TO_SHADOW(kLowShadowEnd)); 36468d75effSDimitry Andric if (kHighMemBeg) { 36568d75effSDimitry Andric Printf(" %p %p", 36668d75effSDimitry Andric (void*)MEM_TO_SHADOW(kHighShadowBeg), 36768d75effSDimitry Andric (void*)MEM_TO_SHADOW(kHighShadowEnd)); 36868d75effSDimitry Andric } 36968d75effSDimitry Andric if (kMidMemBeg) { 37068d75effSDimitry Andric Printf(" %p %p", 37168d75effSDimitry Andric (void*)MEM_TO_SHADOW(kMidShadowBeg), 37268d75effSDimitry Andric (void*)MEM_TO_SHADOW(kMidShadowEnd)); 37368d75effSDimitry Andric } 37468d75effSDimitry Andric Printf("\n"); 37568d75effSDimitry Andric Printf("redzone=%zu\n", (uptr)flags()->redzone); 37668d75effSDimitry Andric Printf("max_redzone=%zu\n", (uptr)flags()->max_redzone); 37768d75effSDimitry Andric Printf("quarantine_size_mb=%zuM\n", (uptr)flags()->quarantine_size_mb); 37868d75effSDimitry Andric Printf("thread_local_quarantine_size_kb=%zuK\n", 37968d75effSDimitry Andric (uptr)flags()->thread_local_quarantine_size_kb); 38068d75effSDimitry Andric Printf("malloc_context_size=%zu\n", 38168d75effSDimitry Andric (uptr)common_flags()->malloc_context_size); 38268d75effSDimitry Andric 3830eae32dcSDimitry Andric Printf("SHADOW_SCALE: %d\n", (int)ASAN_SHADOW_SCALE); 3840eae32dcSDimitry Andric Printf("SHADOW_GRANULARITY: %d\n", (int)ASAN_SHADOW_GRANULARITY); 385*0fca6ea1SDimitry Andric Printf("SHADOW_OFFSET: %p\n", (void *)ASAN_SHADOW_OFFSET); 3860eae32dcSDimitry Andric CHECK(ASAN_SHADOW_SCALE >= 3 && ASAN_SHADOW_SCALE <= 7); 38768d75effSDimitry Andric if (kMidMemBeg) 38868d75effSDimitry Andric CHECK(kMidShadowBeg > kLowShadowEnd && 38968d75effSDimitry Andric kMidMemBeg > kMidShadowEnd && 39068d75effSDimitry Andric kHighShadowBeg > kMidMemEnd); 39168d75effSDimitry Andric } 39268d75effSDimitry Andric 3935f757f3fSDimitry Andric static bool AsanInitInternal() { 3945f757f3fSDimitry Andric if (LIKELY(AsanInited())) 3955f757f3fSDimitry Andric return true; 39668d75effSDimitry Andric SanitizerToolName = "AddressSanitizer"; 39768d75effSDimitry Andric 39868d75effSDimitry Andric CacheBinaryName(); 39968d75effSDimitry Andric 40068d75effSDimitry Andric // Initialize flags. This must be done early, because most of the 40168d75effSDimitry Andric // initialization steps look at flags(). 40268d75effSDimitry Andric InitializeFlags(); 40368d75effSDimitry Andric 40481ad6265SDimitry Andric WaitForDebugger(flags()->sleep_before_init, "before init"); 40581ad6265SDimitry Andric 40668d75effSDimitry Andric // Stop performing init at this point if we are being loaded via 40768d75effSDimitry Andric // dlopen() and the platform supports it. 40868d75effSDimitry Andric if (SANITIZER_SUPPORTS_INIT_FOR_DLOPEN && UNLIKELY(HandleDlopenInit())) { 40968d75effSDimitry Andric VReport(1, "AddressSanitizer init is being performed for dlopen().\n"); 4105f757f3fSDimitry Andric return false; 41168d75effSDimitry Andric } 41268d75effSDimitry Andric 413*0fca6ea1SDimitry Andric // Make sure we are not statically linked. 414*0fca6ea1SDimitry Andric __interception::DoesNotSupportStaticLinking(); 41568d75effSDimitry Andric AsanCheckIncompatibleRT(); 41668d75effSDimitry Andric AsanCheckDynamicRTPrereqs(); 41768d75effSDimitry Andric AvoidCVE_2016_2143(); 41868d75effSDimitry Andric 41968d75effSDimitry Andric SetCanPoisonMemory(flags()->poison_heap); 42068d75effSDimitry Andric SetMallocContextSize(common_flags()->malloc_context_size); 42168d75effSDimitry Andric 42268d75effSDimitry Andric InitializePlatformExceptionHandlers(); 42368d75effSDimitry Andric 42468d75effSDimitry Andric InitializeHighMemEnd(); 42568d75effSDimitry Andric 42668d75effSDimitry Andric // Install tool-specific callbacks in sanitizer_common. 42768d75effSDimitry Andric AddDieCallback(AsanDie); 428fe6060f1SDimitry Andric SetCheckUnwindCallback(CheckUnwind); 42968d75effSDimitry Andric SetPrintfAndReportCallback(AppendToErrorMessageBuffer); 43068d75effSDimitry Andric 43168d75effSDimitry Andric __sanitizer_set_report_path(common_flags()->log_path); 43268d75effSDimitry Andric 43368d75effSDimitry Andric __asan_option_detect_stack_use_after_return = 43468d75effSDimitry Andric flags()->detect_stack_use_after_return; 43568d75effSDimitry Andric 43668d75effSDimitry Andric __sanitizer::InitializePlatformEarly(); 43768d75effSDimitry Andric 43868d75effSDimitry Andric // Setup internal allocator callback. 4390eae32dcSDimitry Andric SetLowLevelAllocateMinAlignment(ASAN_SHADOW_GRANULARITY); 44068d75effSDimitry Andric SetLowLevelAllocateCallback(OnLowLevelAllocate); 44168d75effSDimitry Andric 44268d75effSDimitry Andric InitializeAsanInterceptors(); 44368d75effSDimitry Andric CheckASLR(); 44468d75effSDimitry Andric 44568d75effSDimitry Andric // Enable system log ("adb logcat") on Android. 44668d75effSDimitry Andric // Doing this before interceptors are initialized crashes in: 44768d75effSDimitry Andric // AsanInitInternal -> android_log_write -> __interceptor_strcmp 44868d75effSDimitry Andric AndroidLogInit(); 44968d75effSDimitry Andric 45068d75effSDimitry Andric ReplaceSystemMalloc(); 45168d75effSDimitry Andric 45268d75effSDimitry Andric DisableCoreDumperIfNecessary(); 45368d75effSDimitry Andric 45468d75effSDimitry Andric InitializeShadowMemory(); 45568d75effSDimitry Andric 45668d75effSDimitry Andric AsanTSDInit(PlatformTSDDtor); 45768d75effSDimitry Andric InstallDeadlySignalHandlers(AsanOnDeadlySignal); 45868d75effSDimitry Andric 45968d75effSDimitry Andric AllocatorOptions allocator_options; 46068d75effSDimitry Andric allocator_options.SetFrom(flags(), common_flags()); 46168d75effSDimitry Andric InitializeAllocator(allocator_options); 46268d75effSDimitry Andric 4630eae32dcSDimitry Andric if (SANITIZER_START_BACKGROUND_THREAD_IN_ASAN_INTERNAL) 46468d75effSDimitry Andric MaybeStartBackgroudThread(); 46568d75effSDimitry Andric 46668d75effSDimitry Andric // On Linux AsanThread::ThreadStart() calls malloc() that's why asan_inited 46768d75effSDimitry Andric // should be set to 1 prior to initializing the threads. 468bdd1243dSDimitry Andric replace_intrin_cached = flags()->replace_intrin; 4695f757f3fSDimitry Andric SetAsanInited(); 47068d75effSDimitry Andric 47168d75effSDimitry Andric if (flags()->atexit) 47268d75effSDimitry Andric Atexit(asan_atexit); 47368d75effSDimitry Andric 47468d75effSDimitry Andric InitializeCoverage(common_flags()->coverage, common_flags()->coverage_dir); 47568d75effSDimitry Andric 47668d75effSDimitry Andric // Now that ASan runtime is (mostly) initialized, deactivate it if 47768d75effSDimitry Andric // necessary, so that it can be re-activated when requested. 47868d75effSDimitry Andric if (flags()->start_deactivated) 47968d75effSDimitry Andric AsanDeactivate(); 48068d75effSDimitry Andric 48168d75effSDimitry Andric // interceptors 48268d75effSDimitry Andric InitTlsSize(); 48368d75effSDimitry Andric 48468d75effSDimitry Andric // Create main thread. 48568d75effSDimitry Andric AsanThread *main_thread = CreateMainThread(); 48668d75effSDimitry Andric CHECK_EQ(0, main_thread->tid()); 48768d75effSDimitry Andric force_interface_symbols(); // no-op. 48868d75effSDimitry Andric SanitizerInitializeUnwinder(); 48968d75effSDimitry Andric 49068d75effSDimitry Andric if (CAN_SANITIZE_LEAKS) { 49168d75effSDimitry Andric __lsan::InitCommonLsan(); 49281ad6265SDimitry Andric InstallAtExitCheckLeaks(); 49368d75effSDimitry Andric } 49468d75effSDimitry Andric 4955f757f3fSDimitry Andric InstallAtForkHandler(); 4965f757f3fSDimitry Andric 49768d75effSDimitry Andric #if CAN_SANITIZE_UB 49868d75effSDimitry Andric __ubsan::InitAsPlugin(); 49968d75effSDimitry Andric #endif 50068d75effSDimitry Andric 50168d75effSDimitry Andric InitializeSuppressions(); 50268d75effSDimitry Andric 50368d75effSDimitry Andric if (CAN_SANITIZE_LEAKS) { 50468d75effSDimitry Andric // LateInitialize() calls dlsym, which can allocate an error string buffer 50568d75effSDimitry Andric // in the TLS. Let's ignore the allocation to avoid reporting a leak. 50668d75effSDimitry Andric __lsan::ScopedInterceptorDisabler disabler; 50768d75effSDimitry Andric Symbolizer::LateInitialize(); 50868d75effSDimitry Andric } else { 50968d75effSDimitry Andric Symbolizer::LateInitialize(); 51068d75effSDimitry Andric } 51168d75effSDimitry Andric 51268d75effSDimitry Andric VReport(1, "AddressSanitizer Init done\n"); 51368d75effSDimitry Andric 51481ad6265SDimitry Andric WaitForDebugger(flags()->sleep_after_init, "after init"); 5155f757f3fSDimitry Andric 5165f757f3fSDimitry Andric return true; 51768d75effSDimitry Andric } 51868d75effSDimitry Andric 51968d75effSDimitry Andric // Initialize as requested from some part of ASan runtime library (interceptors, 52068d75effSDimitry Andric // allocator, etc). 52168d75effSDimitry Andric void AsanInitFromRtl() { 5225f757f3fSDimitry Andric if (LIKELY(AsanInited())) 5235f757f3fSDimitry Andric return; 5245f757f3fSDimitry Andric SpinMutexLock lock(&asan_inited_mutex); 52568d75effSDimitry Andric AsanInitInternal(); 52668d75effSDimitry Andric } 52768d75effSDimitry Andric 5285f757f3fSDimitry Andric bool TryAsanInitFromRtl() { 5295f757f3fSDimitry Andric if (LIKELY(AsanInited())) 5305f757f3fSDimitry Andric return true; 5315f757f3fSDimitry Andric if (!asan_inited_mutex.TryLock()) 5325f757f3fSDimitry Andric return false; 5335f757f3fSDimitry Andric bool result = AsanInitInternal(); 5345f757f3fSDimitry Andric asan_inited_mutex.Unlock(); 5355f757f3fSDimitry Andric return result; 5365f757f3fSDimitry Andric } 5375f757f3fSDimitry Andric 53868d75effSDimitry Andric #if ASAN_DYNAMIC 53968d75effSDimitry Andric // Initialize runtime in case it's LD_PRELOAD-ed into unsanitized executable 54068d75effSDimitry Andric // (and thus normal initializers from .preinit_array or modules haven't run). 54168d75effSDimitry Andric 54268d75effSDimitry Andric class AsanInitializer { 54368d75effSDimitry Andric public: 54468d75effSDimitry Andric AsanInitializer() { 54568d75effSDimitry Andric AsanInitFromRtl(); 54668d75effSDimitry Andric } 54768d75effSDimitry Andric }; 54868d75effSDimitry Andric 54968d75effSDimitry Andric static AsanInitializer asan_initializer; 55068d75effSDimitry Andric #endif // ASAN_DYNAMIC 55168d75effSDimitry Andric 5525ffd83dbSDimitry Andric void UnpoisonStack(uptr bottom, uptr top, const char *type) { 5535ffd83dbSDimitry Andric static const uptr kMaxExpectedCleanupSize = 64 << 20; // 64M 5545ffd83dbSDimitry Andric if (top - bottom > kMaxExpectedCleanupSize) { 5555ffd83dbSDimitry Andric static bool reported_warning = false; 5565ffd83dbSDimitry Andric if (reported_warning) 55768d75effSDimitry Andric return; 5585ffd83dbSDimitry Andric reported_warning = true; 5595ffd83dbSDimitry Andric Report( 5605ffd83dbSDimitry Andric "WARNING: ASan is ignoring requested __asan_handle_no_return: " 5615ffd83dbSDimitry Andric "stack type: %s top: %p; bottom %p; size: %p (%zd)\n" 5625ffd83dbSDimitry Andric "False positive error reports may follow\n" 5635ffd83dbSDimitry Andric "For details see " 5645ffd83dbSDimitry Andric "https://github.com/google/sanitizers/issues/189\n", 565349cc55cSDimitry Andric type, (void *)top, (void *)bottom, (void *)(top - bottom), 566349cc55cSDimitry Andric top - bottom); 5675ffd83dbSDimitry Andric return; 5685ffd83dbSDimitry Andric } 5690eae32dcSDimitry Andric PoisonShadow(bottom, RoundUpTo(top - bottom, ASAN_SHADOW_GRANULARITY), 0); 5705ffd83dbSDimitry Andric } 57168d75effSDimitry Andric 5725ffd83dbSDimitry Andric static void UnpoisonDefaultStack() { 5735ffd83dbSDimitry Andric uptr bottom, top; 5745ffd83dbSDimitry Andric 5755ffd83dbSDimitry Andric if (AsanThread *curr_thread = GetCurrentThread()) { 57668d75effSDimitry Andric int local_stack; 5775ffd83dbSDimitry Andric const uptr page_size = GetPageSizeCached(); 57868d75effSDimitry Andric top = curr_thread->stack_top(); 5795ffd83dbSDimitry Andric bottom = ((uptr)&local_stack - page_size) & ~(page_size - 1); 58068d75effSDimitry Andric } else { 58168d75effSDimitry Andric CHECK(!SANITIZER_FUCHSIA); 58268d75effSDimitry Andric // If we haven't seen this thread, try asking the OS for stack bounds. 58368d75effSDimitry Andric uptr tls_addr, tls_size, stack_size; 58468d75effSDimitry Andric GetThreadStackAndTls(/*main=*/false, &bottom, &stack_size, &tls_addr, 58568d75effSDimitry Andric &tls_size); 58668d75effSDimitry Andric top = bottom + stack_size; 58768d75effSDimitry Andric } 5885ffd83dbSDimitry Andric 5895ffd83dbSDimitry Andric UnpoisonStack(bottom, top, "default"); 59068d75effSDimitry Andric } 5915ffd83dbSDimitry Andric 5925ffd83dbSDimitry Andric static void UnpoisonFakeStack() { 5935ffd83dbSDimitry Andric AsanThread *curr_thread = GetCurrentThread(); 594fe6060f1SDimitry Andric if (!curr_thread) 595fe6060f1SDimitry Andric return; 596fe6060f1SDimitry Andric FakeStack *stack = curr_thread->get_fake_stack(); 597fe6060f1SDimitry Andric if (!stack) 598fe6060f1SDimitry Andric return; 599fe6060f1SDimitry Andric stack->HandleNoReturn(); 60068d75effSDimitry Andric } 60168d75effSDimitry Andric 6025ffd83dbSDimitry Andric } // namespace __asan 6035ffd83dbSDimitry Andric 6045ffd83dbSDimitry Andric // ---------------------- Interface ---------------- {{{1 6055ffd83dbSDimitry Andric using namespace __asan; 6065ffd83dbSDimitry Andric 6075ffd83dbSDimitry Andric void NOINLINE __asan_handle_no_return() { 6085f757f3fSDimitry Andric if (UNLIKELY(!AsanInited())) 6095ffd83dbSDimitry Andric return; 6105ffd83dbSDimitry Andric 6115ffd83dbSDimitry Andric if (!PlatformUnpoisonStacks()) 6125ffd83dbSDimitry Andric UnpoisonDefaultStack(); 6135ffd83dbSDimitry Andric 6145ffd83dbSDimitry Andric UnpoisonFakeStack(); 6155ffd83dbSDimitry Andric } 6165ffd83dbSDimitry Andric 61768d75effSDimitry Andric extern "C" void *__asan_extra_spill_area() { 61868d75effSDimitry Andric AsanThread *t = GetCurrentThread(); 61968d75effSDimitry Andric CHECK(t); 62068d75effSDimitry Andric return t->extra_spill_area(); 62168d75effSDimitry Andric } 62268d75effSDimitry Andric 62368d75effSDimitry Andric void __asan_handle_vfork(void *sp) { 62468d75effSDimitry Andric AsanThread *t = GetCurrentThread(); 62568d75effSDimitry Andric CHECK(t); 62668d75effSDimitry Andric uptr bottom = t->stack_bottom(); 62768d75effSDimitry Andric PoisonShadow(bottom, (uptr)sp - bottom, 0); 62868d75effSDimitry Andric } 62968d75effSDimitry Andric 63068d75effSDimitry Andric void NOINLINE __asan_set_death_callback(void (*callback)(void)) { 63168d75effSDimitry Andric SetUserDieCallback(callback); 63268d75effSDimitry Andric } 63368d75effSDimitry Andric 63468d75effSDimitry Andric // Initialize as requested from instrumented application code. 63568d75effSDimitry Andric // We use this call as a trigger to wake up ASan from deactivated state. 63668d75effSDimitry Andric void __asan_init() { 63768d75effSDimitry Andric AsanActivate(); 6385f757f3fSDimitry Andric AsanInitFromRtl(); 63968d75effSDimitry Andric } 64068d75effSDimitry Andric 64168d75effSDimitry Andric void __asan_version_mismatch_check() { 64268d75effSDimitry Andric // Do nothing. 64368d75effSDimitry Andric } 644