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" 1668d75effSDimitry Andric #include "asan_interceptors.h" 1768d75effSDimitry Andric #include "asan_interface_internal.h" 1868d75effSDimitry Andric #include "asan_internal.h" 1968d75effSDimitry Andric #include "asan_mapping.h" 2068d75effSDimitry Andric #include "asan_poisoning.h" 2168d75effSDimitry Andric #include "asan_report.h" 2268d75effSDimitry Andric #include "asan_stack.h" 2368d75effSDimitry Andric #include "asan_stats.h" 2468d75effSDimitry Andric #include "asan_suppressions.h" 2568d75effSDimitry Andric #include "asan_thread.h" 2668d75effSDimitry Andric #include "sanitizer_common/sanitizer_atomic.h" 2768d75effSDimitry Andric #include "sanitizer_common/sanitizer_flags.h" 2868d75effSDimitry Andric #include "sanitizer_common/sanitizer_libc.h" 2968d75effSDimitry Andric #include "sanitizer_common/sanitizer_symbolizer.h" 3068d75effSDimitry Andric #include "lsan/lsan_common.h" 3168d75effSDimitry Andric #include "ubsan/ubsan_init.h" 3268d75effSDimitry Andric #include "ubsan/ubsan_platform.h" 3368d75effSDimitry Andric 3468d75effSDimitry Andric uptr __asan_shadow_memory_dynamic_address; // Global interface symbol. 3568d75effSDimitry Andric int __asan_option_detect_stack_use_after_return; // Global interface symbol. 3668d75effSDimitry Andric uptr *__asan_test_only_reported_buggy_pointer; // Used only for testing asan. 3768d75effSDimitry Andric 3868d75effSDimitry Andric namespace __asan { 3968d75effSDimitry Andric 4068d75effSDimitry Andric uptr AsanMappingProfile[kAsanMappingProfileSize]; 4168d75effSDimitry Andric 4268d75effSDimitry Andric static void AsanDie() { 4368d75effSDimitry Andric static atomic_uint32_t num_calls; 4468d75effSDimitry Andric if (atomic_fetch_add(&num_calls, 1, memory_order_relaxed) != 0) { 4568d75effSDimitry Andric // Don't die twice - run a busy loop. 4668d75effSDimitry Andric while (1) { } 4768d75effSDimitry Andric } 4868d75effSDimitry Andric if (common_flags()->print_module_map >= 1) PrintModuleMap(); 4968d75effSDimitry Andric if (flags()->sleep_before_dying) { 5068d75effSDimitry Andric Report("Sleeping for %d second(s)\n", flags()->sleep_before_dying); 5168d75effSDimitry Andric SleepForSeconds(flags()->sleep_before_dying); 5268d75effSDimitry Andric } 5368d75effSDimitry Andric if (flags()->unmap_shadow_on_exit) { 5468d75effSDimitry Andric if (kMidMemBeg) { 5568d75effSDimitry Andric UnmapOrDie((void*)kLowShadowBeg, kMidMemBeg - kLowShadowBeg); 5668d75effSDimitry Andric UnmapOrDie((void*)kMidMemEnd, kHighShadowEnd - kMidMemEnd); 5768d75effSDimitry Andric } else { 5868d75effSDimitry Andric if (kHighShadowEnd) 5968d75effSDimitry Andric UnmapOrDie((void*)kLowShadowBeg, kHighShadowEnd - kLowShadowBeg); 6068d75effSDimitry Andric } 6168d75effSDimitry Andric } 6268d75effSDimitry Andric } 6368d75effSDimitry Andric 6468d75effSDimitry Andric static void AsanCheckFailed(const char *file, int line, const char *cond, 6568d75effSDimitry Andric u64 v1, u64 v2) { 6668d75effSDimitry Andric Report("AddressSanitizer CHECK failed: %s:%d \"%s\" (0x%zx, 0x%zx)\n", file, 6768d75effSDimitry Andric line, cond, (uptr)v1, (uptr)v2); 6868d75effSDimitry Andric 6968d75effSDimitry Andric // Print a stack trace the first time we come here. Otherwise, we probably 7068d75effSDimitry Andric // failed a CHECK during symbolization. 7168d75effSDimitry Andric static atomic_uint32_t num_calls; 7268d75effSDimitry Andric if (atomic_fetch_add(&num_calls, 1, memory_order_relaxed) == 0) { 7368d75effSDimitry Andric PRINT_CURRENT_STACK_CHECK(); 7468d75effSDimitry Andric } 7568d75effSDimitry Andric 7668d75effSDimitry Andric Die(); 7768d75effSDimitry Andric } 7868d75effSDimitry Andric 7968d75effSDimitry Andric // -------------------------- Globals --------------------- {{{1 8068d75effSDimitry Andric int asan_inited; 8168d75effSDimitry Andric bool asan_init_is_running; 8268d75effSDimitry Andric 8368d75effSDimitry Andric #if !ASAN_FIXED_MAPPING 8468d75effSDimitry Andric uptr kHighMemEnd, kMidMemBeg, kMidMemEnd; 8568d75effSDimitry Andric #endif 8668d75effSDimitry Andric 8768d75effSDimitry Andric // -------------------------- Misc ---------------- {{{1 8868d75effSDimitry Andric void ShowStatsAndAbort() { 8968d75effSDimitry Andric __asan_print_accumulated_stats(); 9068d75effSDimitry Andric Die(); 9168d75effSDimitry Andric } 9268d75effSDimitry Andric 9368d75effSDimitry Andric // --------------- LowLevelAllocateCallbac ---------- {{{1 9468d75effSDimitry Andric static void OnLowLevelAllocate(uptr ptr, uptr size) { 9568d75effSDimitry Andric PoisonShadow(ptr, size, kAsanInternalHeapMagic); 9668d75effSDimitry Andric } 9768d75effSDimitry Andric 9868d75effSDimitry Andric // -------------------------- Run-time entry ------------------- {{{1 9968d75effSDimitry Andric // exported functions 10068d75effSDimitry Andric #define ASAN_REPORT_ERROR(type, is_write, size) \ 10168d75effSDimitry Andric extern "C" NOINLINE INTERFACE_ATTRIBUTE \ 10268d75effSDimitry Andric void __asan_report_ ## type ## size(uptr addr) { \ 10368d75effSDimitry Andric GET_CALLER_PC_BP_SP; \ 10468d75effSDimitry Andric ReportGenericError(pc, bp, sp, addr, is_write, size, 0, true); \ 10568d75effSDimitry Andric } \ 10668d75effSDimitry Andric extern "C" NOINLINE INTERFACE_ATTRIBUTE \ 10768d75effSDimitry Andric void __asan_report_exp_ ## type ## size(uptr addr, u32 exp) { \ 10868d75effSDimitry Andric GET_CALLER_PC_BP_SP; \ 10968d75effSDimitry Andric ReportGenericError(pc, bp, sp, addr, is_write, size, exp, true); \ 11068d75effSDimitry Andric } \ 11168d75effSDimitry Andric extern "C" NOINLINE INTERFACE_ATTRIBUTE \ 11268d75effSDimitry Andric void __asan_report_ ## type ## size ## _noabort(uptr addr) { \ 11368d75effSDimitry Andric GET_CALLER_PC_BP_SP; \ 11468d75effSDimitry Andric ReportGenericError(pc, bp, sp, addr, is_write, size, 0, false); \ 11568d75effSDimitry Andric } \ 11668d75effSDimitry Andric 11768d75effSDimitry Andric ASAN_REPORT_ERROR(load, false, 1) 11868d75effSDimitry Andric ASAN_REPORT_ERROR(load, false, 2) 11968d75effSDimitry Andric ASAN_REPORT_ERROR(load, false, 4) 12068d75effSDimitry Andric ASAN_REPORT_ERROR(load, false, 8) 12168d75effSDimitry Andric ASAN_REPORT_ERROR(load, false, 16) 12268d75effSDimitry Andric ASAN_REPORT_ERROR(store, true, 1) 12368d75effSDimitry Andric ASAN_REPORT_ERROR(store, true, 2) 12468d75effSDimitry Andric ASAN_REPORT_ERROR(store, true, 4) 12568d75effSDimitry Andric ASAN_REPORT_ERROR(store, true, 8) 12668d75effSDimitry Andric ASAN_REPORT_ERROR(store, true, 16) 12768d75effSDimitry Andric 12868d75effSDimitry Andric #define ASAN_REPORT_ERROR_N(type, is_write) \ 12968d75effSDimitry Andric extern "C" NOINLINE INTERFACE_ATTRIBUTE \ 13068d75effSDimitry Andric void __asan_report_ ## type ## _n(uptr addr, uptr size) { \ 13168d75effSDimitry Andric GET_CALLER_PC_BP_SP; \ 13268d75effSDimitry Andric ReportGenericError(pc, bp, sp, addr, is_write, size, 0, true); \ 13368d75effSDimitry Andric } \ 13468d75effSDimitry Andric extern "C" NOINLINE INTERFACE_ATTRIBUTE \ 13568d75effSDimitry Andric void __asan_report_exp_ ## type ## _n(uptr addr, uptr size, u32 exp) { \ 13668d75effSDimitry Andric GET_CALLER_PC_BP_SP; \ 13768d75effSDimitry Andric ReportGenericError(pc, bp, sp, addr, is_write, size, exp, true); \ 13868d75effSDimitry Andric } \ 13968d75effSDimitry Andric extern "C" NOINLINE INTERFACE_ATTRIBUTE \ 14068d75effSDimitry Andric void __asan_report_ ## type ## _n_noabort(uptr addr, uptr size) { \ 14168d75effSDimitry Andric GET_CALLER_PC_BP_SP; \ 14268d75effSDimitry Andric ReportGenericError(pc, bp, sp, addr, is_write, size, 0, false); \ 14368d75effSDimitry Andric } \ 14468d75effSDimitry Andric 14568d75effSDimitry Andric ASAN_REPORT_ERROR_N(load, false) 14668d75effSDimitry Andric ASAN_REPORT_ERROR_N(store, true) 14768d75effSDimitry Andric 14868d75effSDimitry Andric #define ASAN_MEMORY_ACCESS_CALLBACK_BODY(type, is_write, size, exp_arg, fatal) \ 14968d75effSDimitry Andric if (SANITIZER_MYRIAD2 && !AddrIsInMem(addr) && !AddrIsInShadow(addr)) \ 15068d75effSDimitry Andric return; \ 15168d75effSDimitry Andric uptr sp = MEM_TO_SHADOW(addr); \ 15268d75effSDimitry Andric uptr s = size <= SHADOW_GRANULARITY ? *reinterpret_cast<u8 *>(sp) \ 15368d75effSDimitry Andric : *reinterpret_cast<u16 *>(sp); \ 15468d75effSDimitry Andric if (UNLIKELY(s)) { \ 15568d75effSDimitry Andric if (UNLIKELY(size >= SHADOW_GRANULARITY || \ 15668d75effSDimitry Andric ((s8)((addr & (SHADOW_GRANULARITY - 1)) + size - 1)) >= \ 15768d75effSDimitry Andric (s8)s)) { \ 15868d75effSDimitry Andric if (__asan_test_only_reported_buggy_pointer) { \ 15968d75effSDimitry Andric *__asan_test_only_reported_buggy_pointer = addr; \ 16068d75effSDimitry Andric } else { \ 16168d75effSDimitry Andric GET_CALLER_PC_BP_SP; \ 16268d75effSDimitry Andric ReportGenericError(pc, bp, sp, addr, is_write, size, exp_arg, \ 16368d75effSDimitry Andric fatal); \ 16468d75effSDimitry Andric } \ 16568d75effSDimitry Andric } \ 16668d75effSDimitry Andric } 16768d75effSDimitry Andric 16868d75effSDimitry Andric #define ASAN_MEMORY_ACCESS_CALLBACK(type, is_write, size) \ 16968d75effSDimitry Andric extern "C" NOINLINE INTERFACE_ATTRIBUTE \ 17068d75effSDimitry Andric void __asan_##type##size(uptr addr) { \ 17168d75effSDimitry Andric ASAN_MEMORY_ACCESS_CALLBACK_BODY(type, is_write, size, 0, true) \ 17268d75effSDimitry Andric } \ 17368d75effSDimitry Andric extern "C" NOINLINE INTERFACE_ATTRIBUTE \ 17468d75effSDimitry Andric void __asan_exp_##type##size(uptr addr, u32 exp) { \ 17568d75effSDimitry Andric ASAN_MEMORY_ACCESS_CALLBACK_BODY(type, is_write, size, exp, true) \ 17668d75effSDimitry Andric } \ 17768d75effSDimitry Andric extern "C" NOINLINE INTERFACE_ATTRIBUTE \ 17868d75effSDimitry Andric void __asan_##type##size ## _noabort(uptr addr) { \ 17968d75effSDimitry Andric ASAN_MEMORY_ACCESS_CALLBACK_BODY(type, is_write, size, 0, false) \ 18068d75effSDimitry Andric } \ 18168d75effSDimitry Andric 18268d75effSDimitry Andric ASAN_MEMORY_ACCESS_CALLBACK(load, false, 1) 18368d75effSDimitry Andric ASAN_MEMORY_ACCESS_CALLBACK(load, false, 2) 18468d75effSDimitry Andric ASAN_MEMORY_ACCESS_CALLBACK(load, false, 4) 18568d75effSDimitry Andric ASAN_MEMORY_ACCESS_CALLBACK(load, false, 8) 18668d75effSDimitry Andric ASAN_MEMORY_ACCESS_CALLBACK(load, false, 16) 18768d75effSDimitry Andric ASAN_MEMORY_ACCESS_CALLBACK(store, true, 1) 18868d75effSDimitry Andric ASAN_MEMORY_ACCESS_CALLBACK(store, true, 2) 18968d75effSDimitry Andric ASAN_MEMORY_ACCESS_CALLBACK(store, true, 4) 19068d75effSDimitry Andric ASAN_MEMORY_ACCESS_CALLBACK(store, true, 8) 19168d75effSDimitry Andric ASAN_MEMORY_ACCESS_CALLBACK(store, true, 16) 19268d75effSDimitry Andric 19368d75effSDimitry Andric extern "C" 19468d75effSDimitry Andric NOINLINE INTERFACE_ATTRIBUTE 19568d75effSDimitry Andric void __asan_loadN(uptr addr, uptr size) { 19668d75effSDimitry Andric if (__asan_region_is_poisoned(addr, size)) { 19768d75effSDimitry Andric GET_CALLER_PC_BP_SP; 19868d75effSDimitry Andric ReportGenericError(pc, bp, sp, addr, false, size, 0, true); 19968d75effSDimitry Andric } 20068d75effSDimitry Andric } 20168d75effSDimitry Andric 20268d75effSDimitry Andric extern "C" 20368d75effSDimitry Andric NOINLINE INTERFACE_ATTRIBUTE 20468d75effSDimitry Andric void __asan_exp_loadN(uptr addr, uptr size, u32 exp) { 20568d75effSDimitry Andric if (__asan_region_is_poisoned(addr, size)) { 20668d75effSDimitry Andric GET_CALLER_PC_BP_SP; 20768d75effSDimitry Andric ReportGenericError(pc, bp, sp, addr, false, size, exp, true); 20868d75effSDimitry Andric } 20968d75effSDimitry Andric } 21068d75effSDimitry Andric 21168d75effSDimitry Andric extern "C" 21268d75effSDimitry Andric NOINLINE INTERFACE_ATTRIBUTE 21368d75effSDimitry Andric void __asan_loadN_noabort(uptr addr, uptr size) { 21468d75effSDimitry Andric if (__asan_region_is_poisoned(addr, size)) { 21568d75effSDimitry Andric GET_CALLER_PC_BP_SP; 21668d75effSDimitry Andric ReportGenericError(pc, bp, sp, addr, false, size, 0, false); 21768d75effSDimitry Andric } 21868d75effSDimitry Andric } 21968d75effSDimitry Andric 22068d75effSDimitry Andric extern "C" 22168d75effSDimitry Andric NOINLINE INTERFACE_ATTRIBUTE 22268d75effSDimitry Andric void __asan_storeN(uptr addr, uptr size) { 22368d75effSDimitry Andric if (__asan_region_is_poisoned(addr, size)) { 22468d75effSDimitry Andric GET_CALLER_PC_BP_SP; 22568d75effSDimitry Andric ReportGenericError(pc, bp, sp, addr, true, size, 0, true); 22668d75effSDimitry Andric } 22768d75effSDimitry Andric } 22868d75effSDimitry Andric 22968d75effSDimitry Andric extern "C" 23068d75effSDimitry Andric NOINLINE INTERFACE_ATTRIBUTE 23168d75effSDimitry Andric void __asan_exp_storeN(uptr addr, uptr size, u32 exp) { 23268d75effSDimitry Andric if (__asan_region_is_poisoned(addr, size)) { 23368d75effSDimitry Andric GET_CALLER_PC_BP_SP; 23468d75effSDimitry Andric ReportGenericError(pc, bp, sp, addr, true, size, exp, true); 23568d75effSDimitry Andric } 23668d75effSDimitry Andric } 23768d75effSDimitry Andric 23868d75effSDimitry Andric extern "C" 23968d75effSDimitry Andric NOINLINE INTERFACE_ATTRIBUTE 24068d75effSDimitry Andric void __asan_storeN_noabort(uptr addr, uptr size) { 24168d75effSDimitry Andric if (__asan_region_is_poisoned(addr, size)) { 24268d75effSDimitry Andric GET_CALLER_PC_BP_SP; 24368d75effSDimitry Andric ReportGenericError(pc, bp, sp, addr, true, size, 0, false); 24468d75effSDimitry Andric } 24568d75effSDimitry Andric } 24668d75effSDimitry Andric 24768d75effSDimitry Andric // Force the linker to keep the symbols for various ASan interface functions. 24868d75effSDimitry Andric // We want to keep those in the executable in order to let the instrumented 24968d75effSDimitry Andric // dynamic libraries access the symbol even if it is not used by the executable 25068d75effSDimitry Andric // itself. This should help if the build system is removing dead code at link 25168d75effSDimitry Andric // time. 25268d75effSDimitry Andric static NOINLINE void force_interface_symbols() { 25368d75effSDimitry Andric volatile int fake_condition = 0; // prevent dead condition elimination. 25468d75effSDimitry Andric // __asan_report_* functions are noreturn, so we need a switch to prevent 25568d75effSDimitry Andric // the compiler from removing any of them. 25668d75effSDimitry Andric // clang-format off 25768d75effSDimitry Andric switch (fake_condition) { 25868d75effSDimitry Andric case 1: __asan_report_load1(0); break; 25968d75effSDimitry Andric case 2: __asan_report_load2(0); break; 26068d75effSDimitry Andric case 3: __asan_report_load4(0); break; 26168d75effSDimitry Andric case 4: __asan_report_load8(0); break; 26268d75effSDimitry Andric case 5: __asan_report_load16(0); break; 26368d75effSDimitry Andric case 6: __asan_report_load_n(0, 0); break; 26468d75effSDimitry Andric case 7: __asan_report_store1(0); break; 26568d75effSDimitry Andric case 8: __asan_report_store2(0); break; 26668d75effSDimitry Andric case 9: __asan_report_store4(0); break; 26768d75effSDimitry Andric case 10: __asan_report_store8(0); break; 26868d75effSDimitry Andric case 11: __asan_report_store16(0); break; 26968d75effSDimitry Andric case 12: __asan_report_store_n(0, 0); break; 27068d75effSDimitry Andric case 13: __asan_report_exp_load1(0, 0); break; 27168d75effSDimitry Andric case 14: __asan_report_exp_load2(0, 0); break; 27268d75effSDimitry Andric case 15: __asan_report_exp_load4(0, 0); break; 27368d75effSDimitry Andric case 16: __asan_report_exp_load8(0, 0); break; 27468d75effSDimitry Andric case 17: __asan_report_exp_load16(0, 0); break; 27568d75effSDimitry Andric case 18: __asan_report_exp_load_n(0, 0, 0); break; 27668d75effSDimitry Andric case 19: __asan_report_exp_store1(0, 0); break; 27768d75effSDimitry Andric case 20: __asan_report_exp_store2(0, 0); break; 27868d75effSDimitry Andric case 21: __asan_report_exp_store4(0, 0); break; 27968d75effSDimitry Andric case 22: __asan_report_exp_store8(0, 0); break; 28068d75effSDimitry Andric case 23: __asan_report_exp_store16(0, 0); break; 28168d75effSDimitry Andric case 24: __asan_report_exp_store_n(0, 0, 0); break; 28268d75effSDimitry Andric case 25: __asan_register_globals(nullptr, 0); break; 28368d75effSDimitry Andric case 26: __asan_unregister_globals(nullptr, 0); break; 28468d75effSDimitry Andric case 27: __asan_set_death_callback(nullptr); break; 28568d75effSDimitry Andric case 28: __asan_set_error_report_callback(nullptr); break; 28668d75effSDimitry Andric case 29: __asan_handle_no_return(); break; 28768d75effSDimitry Andric case 30: __asan_address_is_poisoned(nullptr); break; 28868d75effSDimitry Andric case 31: __asan_poison_memory_region(nullptr, 0); break; 28968d75effSDimitry Andric case 32: __asan_unpoison_memory_region(nullptr, 0); break; 29068d75effSDimitry Andric case 34: __asan_before_dynamic_init(nullptr); break; 29168d75effSDimitry Andric case 35: __asan_after_dynamic_init(); break; 29268d75effSDimitry Andric case 36: __asan_poison_stack_memory(0, 0); break; 29368d75effSDimitry Andric case 37: __asan_unpoison_stack_memory(0, 0); break; 29468d75effSDimitry Andric case 38: __asan_region_is_poisoned(0, 0); break; 29568d75effSDimitry Andric case 39: __asan_describe_address(0); break; 29668d75effSDimitry Andric case 40: __asan_set_shadow_00(0, 0); break; 29768d75effSDimitry Andric case 41: __asan_set_shadow_f1(0, 0); break; 29868d75effSDimitry Andric case 42: __asan_set_shadow_f2(0, 0); break; 29968d75effSDimitry Andric case 43: __asan_set_shadow_f3(0, 0); break; 30068d75effSDimitry Andric case 44: __asan_set_shadow_f5(0, 0); break; 30168d75effSDimitry Andric case 45: __asan_set_shadow_f8(0, 0); break; 30268d75effSDimitry Andric } 30368d75effSDimitry Andric // clang-format on 30468d75effSDimitry Andric } 30568d75effSDimitry Andric 30668d75effSDimitry Andric static void asan_atexit() { 30768d75effSDimitry Andric Printf("AddressSanitizer exit stats:\n"); 30868d75effSDimitry Andric __asan_print_accumulated_stats(); 30968d75effSDimitry Andric // Print AsanMappingProfile. 31068d75effSDimitry Andric for (uptr i = 0; i < kAsanMappingProfileSize; i++) { 31168d75effSDimitry Andric if (AsanMappingProfile[i] == 0) continue; 31268d75effSDimitry Andric Printf("asan_mapping.h:%zd -- %zd\n", i, AsanMappingProfile[i]); 31368d75effSDimitry Andric } 31468d75effSDimitry Andric } 31568d75effSDimitry Andric 31668d75effSDimitry Andric static void InitializeHighMemEnd() { 31768d75effSDimitry Andric #if !SANITIZER_MYRIAD2 31868d75effSDimitry Andric #if !ASAN_FIXED_MAPPING 31968d75effSDimitry Andric kHighMemEnd = GetMaxUserVirtualAddress(); 32068d75effSDimitry Andric // Increase kHighMemEnd to make sure it's properly 32168d75effSDimitry Andric // aligned together with kHighMemBeg: 32268d75effSDimitry Andric kHighMemEnd |= SHADOW_GRANULARITY * GetMmapGranularity() - 1; 32368d75effSDimitry Andric #endif // !ASAN_FIXED_MAPPING 32468d75effSDimitry Andric CHECK_EQ((kHighMemBeg % GetMmapGranularity()), 0); 32568d75effSDimitry Andric #endif // !SANITIZER_MYRIAD2 32668d75effSDimitry Andric } 32768d75effSDimitry Andric 32868d75effSDimitry Andric void PrintAddressSpaceLayout() { 32968d75effSDimitry Andric if (kHighMemBeg) { 33068d75effSDimitry Andric Printf("|| `[%p, %p]` || HighMem ||\n", 33168d75effSDimitry Andric (void*)kHighMemBeg, (void*)kHighMemEnd); 33268d75effSDimitry Andric Printf("|| `[%p, %p]` || HighShadow ||\n", 33368d75effSDimitry Andric (void*)kHighShadowBeg, (void*)kHighShadowEnd); 33468d75effSDimitry Andric } 33568d75effSDimitry Andric if (kMidMemBeg) { 33668d75effSDimitry Andric Printf("|| `[%p, %p]` || ShadowGap3 ||\n", 33768d75effSDimitry Andric (void*)kShadowGap3Beg, (void*)kShadowGap3End); 33868d75effSDimitry Andric Printf("|| `[%p, %p]` || MidMem ||\n", 33968d75effSDimitry Andric (void*)kMidMemBeg, (void*)kMidMemEnd); 34068d75effSDimitry Andric Printf("|| `[%p, %p]` || ShadowGap2 ||\n", 34168d75effSDimitry Andric (void*)kShadowGap2Beg, (void*)kShadowGap2End); 34268d75effSDimitry Andric Printf("|| `[%p, %p]` || MidShadow ||\n", 34368d75effSDimitry Andric (void*)kMidShadowBeg, (void*)kMidShadowEnd); 34468d75effSDimitry Andric } 34568d75effSDimitry Andric Printf("|| `[%p, %p]` || ShadowGap ||\n", 34668d75effSDimitry Andric (void*)kShadowGapBeg, (void*)kShadowGapEnd); 34768d75effSDimitry Andric if (kLowShadowBeg) { 34868d75effSDimitry Andric Printf("|| `[%p, %p]` || LowShadow ||\n", 34968d75effSDimitry Andric (void*)kLowShadowBeg, (void*)kLowShadowEnd); 35068d75effSDimitry Andric Printf("|| `[%p, %p]` || LowMem ||\n", 35168d75effSDimitry Andric (void*)kLowMemBeg, (void*)kLowMemEnd); 35268d75effSDimitry Andric } 35368d75effSDimitry Andric Printf("MemToShadow(shadow): %p %p", 35468d75effSDimitry Andric (void*)MEM_TO_SHADOW(kLowShadowBeg), 35568d75effSDimitry Andric (void*)MEM_TO_SHADOW(kLowShadowEnd)); 35668d75effSDimitry Andric if (kHighMemBeg) { 35768d75effSDimitry Andric Printf(" %p %p", 35868d75effSDimitry Andric (void*)MEM_TO_SHADOW(kHighShadowBeg), 35968d75effSDimitry Andric (void*)MEM_TO_SHADOW(kHighShadowEnd)); 36068d75effSDimitry Andric } 36168d75effSDimitry Andric if (kMidMemBeg) { 36268d75effSDimitry Andric Printf(" %p %p", 36368d75effSDimitry Andric (void*)MEM_TO_SHADOW(kMidShadowBeg), 36468d75effSDimitry Andric (void*)MEM_TO_SHADOW(kMidShadowEnd)); 36568d75effSDimitry Andric } 36668d75effSDimitry Andric Printf("\n"); 36768d75effSDimitry Andric Printf("redzone=%zu\n", (uptr)flags()->redzone); 36868d75effSDimitry Andric Printf("max_redzone=%zu\n", (uptr)flags()->max_redzone); 36968d75effSDimitry Andric Printf("quarantine_size_mb=%zuM\n", (uptr)flags()->quarantine_size_mb); 37068d75effSDimitry Andric Printf("thread_local_quarantine_size_kb=%zuK\n", 37168d75effSDimitry Andric (uptr)flags()->thread_local_quarantine_size_kb); 37268d75effSDimitry Andric Printf("malloc_context_size=%zu\n", 37368d75effSDimitry Andric (uptr)common_flags()->malloc_context_size); 37468d75effSDimitry Andric 37568d75effSDimitry Andric Printf("SHADOW_SCALE: %d\n", (int)SHADOW_SCALE); 37668d75effSDimitry Andric Printf("SHADOW_GRANULARITY: %d\n", (int)SHADOW_GRANULARITY); 37768d75effSDimitry Andric Printf("SHADOW_OFFSET: 0x%zx\n", (uptr)SHADOW_OFFSET); 37868d75effSDimitry Andric CHECK(SHADOW_SCALE >= 3 && SHADOW_SCALE <= 7); 37968d75effSDimitry Andric if (kMidMemBeg) 38068d75effSDimitry Andric CHECK(kMidShadowBeg > kLowShadowEnd && 38168d75effSDimitry Andric kMidMemBeg > kMidShadowEnd && 38268d75effSDimitry Andric kHighShadowBeg > kMidMemEnd); 38368d75effSDimitry Andric } 38468d75effSDimitry Andric 38568d75effSDimitry Andric #if defined(__thumb__) && defined(__linux__) 38668d75effSDimitry Andric #define START_BACKGROUND_THREAD_IN_ASAN_INTERNAL 38768d75effSDimitry Andric #endif 38868d75effSDimitry Andric 38968d75effSDimitry Andric #ifndef START_BACKGROUND_THREAD_IN_ASAN_INTERNAL 39068d75effSDimitry Andric static bool UNUSED __local_asan_dyninit = [] { 39168d75effSDimitry Andric MaybeStartBackgroudThread(); 39268d75effSDimitry Andric SetSoftRssLimitExceededCallback(AsanSoftRssLimitExceededCallback); 39368d75effSDimitry Andric 39468d75effSDimitry Andric return false; 39568d75effSDimitry Andric }(); 39668d75effSDimitry Andric #endif 39768d75effSDimitry Andric 39868d75effSDimitry Andric static void AsanInitInternal() { 39968d75effSDimitry Andric if (LIKELY(asan_inited)) return; 40068d75effSDimitry Andric SanitizerToolName = "AddressSanitizer"; 40168d75effSDimitry Andric CHECK(!asan_init_is_running && "ASan init calls itself!"); 40268d75effSDimitry Andric asan_init_is_running = true; 40368d75effSDimitry Andric 40468d75effSDimitry Andric CacheBinaryName(); 40568d75effSDimitry Andric 40668d75effSDimitry Andric // Initialize flags. This must be done early, because most of the 40768d75effSDimitry Andric // initialization steps look at flags(). 40868d75effSDimitry Andric InitializeFlags(); 40968d75effSDimitry Andric 41068d75effSDimitry Andric // Stop performing init at this point if we are being loaded via 41168d75effSDimitry Andric // dlopen() and the platform supports it. 41268d75effSDimitry Andric if (SANITIZER_SUPPORTS_INIT_FOR_DLOPEN && UNLIKELY(HandleDlopenInit())) { 41368d75effSDimitry Andric asan_init_is_running = false; 41468d75effSDimitry Andric VReport(1, "AddressSanitizer init is being performed for dlopen().\n"); 41568d75effSDimitry Andric return; 41668d75effSDimitry Andric } 41768d75effSDimitry Andric 41868d75effSDimitry Andric AsanCheckIncompatibleRT(); 41968d75effSDimitry Andric AsanCheckDynamicRTPrereqs(); 42068d75effSDimitry Andric AvoidCVE_2016_2143(); 42168d75effSDimitry Andric 42268d75effSDimitry Andric SetCanPoisonMemory(flags()->poison_heap); 42368d75effSDimitry Andric SetMallocContextSize(common_flags()->malloc_context_size); 42468d75effSDimitry Andric 42568d75effSDimitry Andric InitializePlatformExceptionHandlers(); 42668d75effSDimitry Andric 42768d75effSDimitry Andric InitializeHighMemEnd(); 42868d75effSDimitry Andric 42968d75effSDimitry Andric // Make sure we are not statically linked. 43068d75effSDimitry Andric AsanDoesNotSupportStaticLinkage(); 43168d75effSDimitry Andric 43268d75effSDimitry Andric // Install tool-specific callbacks in sanitizer_common. 43368d75effSDimitry Andric AddDieCallback(AsanDie); 43468d75effSDimitry Andric SetCheckFailedCallback(AsanCheckFailed); 43568d75effSDimitry Andric SetPrintfAndReportCallback(AppendToErrorMessageBuffer); 43668d75effSDimitry Andric 43768d75effSDimitry Andric __sanitizer_set_report_path(common_flags()->log_path); 43868d75effSDimitry Andric 43968d75effSDimitry Andric __asan_option_detect_stack_use_after_return = 44068d75effSDimitry Andric flags()->detect_stack_use_after_return; 44168d75effSDimitry Andric 44268d75effSDimitry Andric __sanitizer::InitializePlatformEarly(); 44368d75effSDimitry Andric 44468d75effSDimitry Andric // Re-exec ourselves if we need to set additional env or command line args. 44568d75effSDimitry Andric MaybeReexec(); 44668d75effSDimitry Andric 44768d75effSDimitry Andric // Setup internal allocator callback. 44868d75effSDimitry Andric SetLowLevelAllocateMinAlignment(SHADOW_GRANULARITY); 44968d75effSDimitry Andric SetLowLevelAllocateCallback(OnLowLevelAllocate); 45068d75effSDimitry Andric 45168d75effSDimitry Andric InitializeAsanInterceptors(); 45268d75effSDimitry Andric CheckASLR(); 45368d75effSDimitry Andric 45468d75effSDimitry Andric // Enable system log ("adb logcat") on Android. 45568d75effSDimitry Andric // Doing this before interceptors are initialized crashes in: 45668d75effSDimitry Andric // AsanInitInternal -> android_log_write -> __interceptor_strcmp 45768d75effSDimitry Andric AndroidLogInit(); 45868d75effSDimitry Andric 45968d75effSDimitry Andric ReplaceSystemMalloc(); 46068d75effSDimitry Andric 46168d75effSDimitry Andric DisableCoreDumperIfNecessary(); 46268d75effSDimitry Andric 46368d75effSDimitry Andric InitializeShadowMemory(); 46468d75effSDimitry Andric 46568d75effSDimitry Andric AsanTSDInit(PlatformTSDDtor); 46668d75effSDimitry Andric InstallDeadlySignalHandlers(AsanOnDeadlySignal); 46768d75effSDimitry Andric 46868d75effSDimitry Andric AllocatorOptions allocator_options; 46968d75effSDimitry Andric allocator_options.SetFrom(flags(), common_flags()); 47068d75effSDimitry Andric InitializeAllocator(allocator_options); 47168d75effSDimitry Andric 47268d75effSDimitry Andric #ifdef START_BACKGROUND_THREAD_IN_ASAN_INTERNAL 47368d75effSDimitry Andric MaybeStartBackgroudThread(); 47468d75effSDimitry Andric SetSoftRssLimitExceededCallback(AsanSoftRssLimitExceededCallback); 47568d75effSDimitry Andric #endif 47668d75effSDimitry Andric 47768d75effSDimitry Andric // On Linux AsanThread::ThreadStart() calls malloc() that's why asan_inited 47868d75effSDimitry Andric // should be set to 1 prior to initializing the threads. 47968d75effSDimitry Andric asan_inited = 1; 48068d75effSDimitry Andric asan_init_is_running = false; 48168d75effSDimitry Andric 48268d75effSDimitry Andric if (flags()->atexit) 48368d75effSDimitry Andric Atexit(asan_atexit); 48468d75effSDimitry Andric 48568d75effSDimitry Andric InitializeCoverage(common_flags()->coverage, common_flags()->coverage_dir); 48668d75effSDimitry Andric 48768d75effSDimitry Andric // Now that ASan runtime is (mostly) initialized, deactivate it if 48868d75effSDimitry Andric // necessary, so that it can be re-activated when requested. 48968d75effSDimitry Andric if (flags()->start_deactivated) 49068d75effSDimitry Andric AsanDeactivate(); 49168d75effSDimitry Andric 49268d75effSDimitry Andric // interceptors 49368d75effSDimitry Andric InitTlsSize(); 49468d75effSDimitry Andric 49568d75effSDimitry Andric // Create main thread. 49668d75effSDimitry Andric AsanThread *main_thread = CreateMainThread(); 49768d75effSDimitry Andric CHECK_EQ(0, main_thread->tid()); 49868d75effSDimitry Andric force_interface_symbols(); // no-op. 49968d75effSDimitry Andric SanitizerInitializeUnwinder(); 50068d75effSDimitry Andric 50168d75effSDimitry Andric if (CAN_SANITIZE_LEAKS) { 50268d75effSDimitry Andric __lsan::InitCommonLsan(); 50368d75effSDimitry Andric if (common_flags()->detect_leaks && common_flags()->leak_check_at_exit) { 50468d75effSDimitry Andric if (flags()->halt_on_error) 50568d75effSDimitry Andric Atexit(__lsan::DoLeakCheck); 50668d75effSDimitry Andric else 50768d75effSDimitry Andric Atexit(__lsan::DoRecoverableLeakCheckVoid); 50868d75effSDimitry Andric } 50968d75effSDimitry Andric } 51068d75effSDimitry Andric 51168d75effSDimitry Andric #if CAN_SANITIZE_UB 51268d75effSDimitry Andric __ubsan::InitAsPlugin(); 51368d75effSDimitry Andric #endif 51468d75effSDimitry Andric 51568d75effSDimitry Andric InitializeSuppressions(); 51668d75effSDimitry Andric 51768d75effSDimitry Andric if (CAN_SANITIZE_LEAKS) { 51868d75effSDimitry Andric // LateInitialize() calls dlsym, which can allocate an error string buffer 51968d75effSDimitry Andric // in the TLS. Let's ignore the allocation to avoid reporting a leak. 52068d75effSDimitry Andric __lsan::ScopedInterceptorDisabler disabler; 52168d75effSDimitry Andric Symbolizer::LateInitialize(); 52268d75effSDimitry Andric } else { 52368d75effSDimitry Andric Symbolizer::LateInitialize(); 52468d75effSDimitry Andric } 52568d75effSDimitry Andric 52668d75effSDimitry Andric VReport(1, "AddressSanitizer Init done\n"); 52768d75effSDimitry Andric 52868d75effSDimitry Andric if (flags()->sleep_after_init) { 52968d75effSDimitry Andric Report("Sleeping for %d second(s)\n", flags()->sleep_after_init); 53068d75effSDimitry Andric SleepForSeconds(flags()->sleep_after_init); 53168d75effSDimitry Andric } 53268d75effSDimitry Andric } 53368d75effSDimitry Andric 53468d75effSDimitry Andric // Initialize as requested from some part of ASan runtime library (interceptors, 53568d75effSDimitry Andric // allocator, etc). 53668d75effSDimitry Andric void AsanInitFromRtl() { 53768d75effSDimitry Andric AsanInitInternal(); 53868d75effSDimitry Andric } 53968d75effSDimitry Andric 54068d75effSDimitry Andric #if ASAN_DYNAMIC 54168d75effSDimitry Andric // Initialize runtime in case it's LD_PRELOAD-ed into unsanitized executable 54268d75effSDimitry Andric // (and thus normal initializers from .preinit_array or modules haven't run). 54368d75effSDimitry Andric 54468d75effSDimitry Andric class AsanInitializer { 54568d75effSDimitry Andric public: 54668d75effSDimitry Andric AsanInitializer() { 54768d75effSDimitry Andric AsanInitFromRtl(); 54868d75effSDimitry Andric } 54968d75effSDimitry Andric }; 55068d75effSDimitry Andric 55168d75effSDimitry Andric static AsanInitializer asan_initializer; 55268d75effSDimitry Andric #endif // ASAN_DYNAMIC 55368d75effSDimitry Andric 554*5ffd83dbSDimitry Andric void UnpoisonStack(uptr bottom, uptr top, const char *type) { 555*5ffd83dbSDimitry Andric static const uptr kMaxExpectedCleanupSize = 64 << 20; // 64M 556*5ffd83dbSDimitry Andric if (top - bottom > kMaxExpectedCleanupSize) { 557*5ffd83dbSDimitry Andric static bool reported_warning = false; 558*5ffd83dbSDimitry Andric if (reported_warning) 55968d75effSDimitry Andric return; 560*5ffd83dbSDimitry Andric reported_warning = true; 561*5ffd83dbSDimitry Andric Report( 562*5ffd83dbSDimitry Andric "WARNING: ASan is ignoring requested __asan_handle_no_return: " 563*5ffd83dbSDimitry Andric "stack type: %s top: %p; bottom %p; size: %p (%zd)\n" 564*5ffd83dbSDimitry Andric "False positive error reports may follow\n" 565*5ffd83dbSDimitry Andric "For details see " 566*5ffd83dbSDimitry Andric "https://github.com/google/sanitizers/issues/189\n", 567*5ffd83dbSDimitry Andric type, top, bottom, top - bottom, top - bottom); 568*5ffd83dbSDimitry Andric return; 569*5ffd83dbSDimitry Andric } 570*5ffd83dbSDimitry Andric PoisonShadow(bottom, top - bottom, 0); 571*5ffd83dbSDimitry Andric } 57268d75effSDimitry Andric 573*5ffd83dbSDimitry Andric static void UnpoisonDefaultStack() { 574*5ffd83dbSDimitry Andric uptr bottom, top; 575*5ffd83dbSDimitry Andric 576*5ffd83dbSDimitry Andric if (AsanThread *curr_thread = GetCurrentThread()) { 57768d75effSDimitry Andric int local_stack; 578*5ffd83dbSDimitry Andric const uptr page_size = GetPageSizeCached(); 57968d75effSDimitry Andric top = curr_thread->stack_top(); 580*5ffd83dbSDimitry Andric bottom = ((uptr)&local_stack - page_size) & ~(page_size - 1); 58168d75effSDimitry Andric } else if (SANITIZER_RTEMS) { 58268d75effSDimitry Andric // Give up On RTEMS. 58368d75effSDimitry Andric return; 58468d75effSDimitry Andric } else { 58568d75effSDimitry Andric CHECK(!SANITIZER_FUCHSIA); 58668d75effSDimitry Andric // If we haven't seen this thread, try asking the OS for stack bounds. 58768d75effSDimitry Andric uptr tls_addr, tls_size, stack_size; 58868d75effSDimitry Andric GetThreadStackAndTls(/*main=*/false, &bottom, &stack_size, &tls_addr, 58968d75effSDimitry Andric &tls_size); 59068d75effSDimitry Andric top = bottom + stack_size; 59168d75effSDimitry Andric } 592*5ffd83dbSDimitry Andric 593*5ffd83dbSDimitry Andric UnpoisonStack(bottom, top, "default"); 59468d75effSDimitry Andric } 595*5ffd83dbSDimitry Andric 596*5ffd83dbSDimitry Andric static void UnpoisonFakeStack() { 597*5ffd83dbSDimitry Andric AsanThread *curr_thread = GetCurrentThread(); 59868d75effSDimitry Andric if (curr_thread && curr_thread->has_fake_stack()) 59968d75effSDimitry Andric curr_thread->fake_stack()->HandleNoReturn(); 60068d75effSDimitry Andric } 60168d75effSDimitry Andric 602*5ffd83dbSDimitry Andric } // namespace __asan 603*5ffd83dbSDimitry Andric 604*5ffd83dbSDimitry Andric // ---------------------- Interface ---------------- {{{1 605*5ffd83dbSDimitry Andric using namespace __asan; 606*5ffd83dbSDimitry Andric 607*5ffd83dbSDimitry Andric void NOINLINE __asan_handle_no_return() { 608*5ffd83dbSDimitry Andric if (asan_init_is_running) 609*5ffd83dbSDimitry Andric return; 610*5ffd83dbSDimitry Andric 611*5ffd83dbSDimitry Andric if (!PlatformUnpoisonStacks()) 612*5ffd83dbSDimitry Andric UnpoisonDefaultStack(); 613*5ffd83dbSDimitry Andric 614*5ffd83dbSDimitry Andric UnpoisonFakeStack(); 615*5ffd83dbSDimitry Andric } 616*5ffd83dbSDimitry 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(); 63868d75effSDimitry Andric AsanInitInternal(); 63968d75effSDimitry Andric } 64068d75effSDimitry Andric 64168d75effSDimitry Andric void __asan_version_mismatch_check() { 64268d75effSDimitry Andric // Do nothing. 64368d75effSDimitry Andric } 644