1217222abSNico Weber //===-- asan_rtl.cpp ------------------------------------------------------===// 2217222abSNico Weber // 3217222abSNico Weber // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4217222abSNico Weber // See https://llvm.org/LICENSE.txt for license information. 5217222abSNico Weber // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6217222abSNico Weber // 7217222abSNico Weber //===----------------------------------------------------------------------===// 8217222abSNico Weber // 9217222abSNico Weber // This file is a part of AddressSanitizer, an address sanity checker. 10217222abSNico Weber // 11217222abSNico Weber // Main file of the ASan run-time library. 12217222abSNico Weber //===----------------------------------------------------------------------===// 13217222abSNico Weber 14217222abSNico Weber #include "asan_activation.h" 15217222abSNico Weber #include "asan_allocator.h" 165b0e5055SVitaly Buka #include "asan_fake_stack.h" 17217222abSNico Weber #include "asan_interceptors.h" 18217222abSNico Weber #include "asan_interface_internal.h" 19217222abSNico Weber #include "asan_internal.h" 20217222abSNico Weber #include "asan_mapping.h" 21217222abSNico Weber #include "asan_poisoning.h" 22217222abSNico Weber #include "asan_report.h" 23217222abSNico Weber #include "asan_stack.h" 24217222abSNico Weber #include "asan_stats.h" 25217222abSNico Weber #include "asan_suppressions.h" 26217222abSNico Weber #include "asan_thread.h" 2764b1cbcaSVitaly Buka #include "lsan/lsan_common.h" 28217222abSNico Weber #include "sanitizer_common/sanitizer_atomic.h" 29217222abSNico Weber #include "sanitizer_common/sanitizer_flags.h" 30595d340dSDmitry Vyukov #include "sanitizer_common/sanitizer_interface_internal.h" 31217222abSNico Weber #include "sanitizer_common/sanitizer_libc.h" 32217222abSNico Weber #include "sanitizer_common/sanitizer_symbolizer.h" 33217222abSNico Weber #include "ubsan/ubsan_init.h" 34217222abSNico Weber #include "ubsan/ubsan_platform.h" 35217222abSNico Weber 36217222abSNico Weber uptr __asan_shadow_memory_dynamic_address; // Global interface symbol. 37217222abSNico Weber int __asan_option_detect_stack_use_after_return; // Global interface symbol. 38217222abSNico Weber uptr *__asan_test_only_reported_buggy_pointer; // Used only for testing asan. 39217222abSNico Weber 40217222abSNico Weber namespace __asan { 41217222abSNico Weber 42217222abSNico Weber uptr AsanMappingProfile[kAsanMappingProfileSize]; 43217222abSNico Weber 44217222abSNico Weber static void AsanDie() { 45217222abSNico Weber static atomic_uint32_t num_calls; 46217222abSNico Weber if (atomic_fetch_add(&num_calls, 1, memory_order_relaxed) != 0) { 47217222abSNico Weber // Don't die twice - run a busy loop. 48d49aaaf4SFlorian Mayer while (1) { 49d49aaaf4SFlorian Mayer internal_sched_yield(); 50d49aaaf4SFlorian Mayer } 51217222abSNico Weber } 5231bc55d6STeresa Johnson if (common_flags()->print_module_map >= 1) 5331bc55d6STeresa Johnson DumpProcessMap(); 54ec563c5aSJulian Lettner 55ec563c5aSJulian Lettner WaitForDebugger(flags()->sleep_before_dying, "before dying"); 56ec563c5aSJulian Lettner 57217222abSNico Weber if (flags()->unmap_shadow_on_exit) { 58217222abSNico Weber if (kMidMemBeg) { 59217222abSNico Weber UnmapOrDie((void*)kLowShadowBeg, kMidMemBeg - kLowShadowBeg); 60217222abSNico Weber UnmapOrDie((void*)kMidMemEnd, kHighShadowEnd - kMidMemEnd); 61217222abSNico Weber } else { 62217222abSNico Weber if (kHighShadowEnd) 63217222abSNico Weber UnmapOrDie((void*)kLowShadowBeg, kHighShadowEnd - kLowShadowBeg); 64217222abSNico Weber } 65217222abSNico Weber } 66217222abSNico Weber } 67217222abSNico Weber 682721e27cSDmitry Vyukov static void CheckUnwind() { 692721e27cSDmitry Vyukov GET_STACK_TRACE(kStackTraceMax, common_flags()->fast_unwind_on_check); 702721e27cSDmitry Vyukov stack.Print(); 71217222abSNico Weber } 72217222abSNico Weber 73217222abSNico Weber // -------------------------- Globals --------------------- {{{1 749567b33fSVitaly Buka static StaticSpinMutex asan_inited_mutex; 759567b33fSVitaly Buka static atomic_uint8_t asan_inited = {0}; 765d6304f0SZachary Johnson 779567b33fSVitaly Buka static void SetAsanInited() { 789567b33fSVitaly Buka atomic_store(&asan_inited, 1, memory_order_release); 799567b33fSVitaly Buka } 805d6304f0SZachary Johnson 819567b33fSVitaly Buka bool AsanInited() { 829567b33fSVitaly Buka return atomic_load(&asan_inited, memory_order_acquire) == 1; 839567b33fSVitaly Buka } 845d6304f0SZachary Johnson 8503e345b5SVitaly Buka bool replace_intrin_cached; 86217222abSNico Weber 87217222abSNico Weber #if !ASAN_FIXED_MAPPING 88217222abSNico Weber uptr kHighMemEnd, kMidMemBeg, kMidMemEnd; 89217222abSNico Weber #endif 90217222abSNico Weber 91217222abSNico Weber // -------------------------- Misc ---------------- {{{1 92217222abSNico Weber void ShowStatsAndAbort() { 93217222abSNico Weber __asan_print_accumulated_stats(); 94217222abSNico Weber Die(); 95217222abSNico Weber } 96217222abSNico Weber 977de73da8SKirill Stoimenov NOINLINE 987de73da8SKirill Stoimenov static void ReportGenericErrorWrapper(uptr addr, bool is_write, int size, 997de73da8SKirill Stoimenov int exp_arg, bool fatal) { 1007de73da8SKirill Stoimenov GET_CALLER_PC_BP_SP; 1017de73da8SKirill Stoimenov ReportGenericError(pc, bp, sp, addr, is_write, size, exp_arg, fatal); 1027de73da8SKirill Stoimenov } 1037de73da8SKirill Stoimenov 104217222abSNico Weber // --------------- LowLevelAllocateCallbac ---------- {{{1 105217222abSNico Weber static void OnLowLevelAllocate(uptr ptr, uptr size) { 106217222abSNico Weber PoisonShadow(ptr, size, kAsanInternalHeapMagic); 107217222abSNico Weber } 108217222abSNico Weber 109217222abSNico Weber // -------------------------- Run-time entry ------------------- {{{1 110217222abSNico Weber // exported functions 111217222abSNico Weber #define ASAN_REPORT_ERROR(type, is_write, size) \ 112217222abSNico Weber extern "C" NOINLINE INTERFACE_ATTRIBUTE \ 113217222abSNico Weber void __asan_report_ ## type ## size(uptr addr) { \ 114217222abSNico Weber GET_CALLER_PC_BP_SP; \ 115217222abSNico Weber ReportGenericError(pc, bp, sp, addr, is_write, size, 0, true); \ 116217222abSNico Weber } \ 117217222abSNico Weber extern "C" NOINLINE INTERFACE_ATTRIBUTE \ 118217222abSNico Weber void __asan_report_exp_ ## type ## size(uptr addr, u32 exp) { \ 119217222abSNico Weber GET_CALLER_PC_BP_SP; \ 120217222abSNico Weber ReportGenericError(pc, bp, sp, addr, is_write, size, exp, true); \ 121217222abSNico Weber } \ 122217222abSNico Weber extern "C" NOINLINE INTERFACE_ATTRIBUTE \ 123217222abSNico Weber void __asan_report_ ## type ## size ## _noabort(uptr addr) { \ 124217222abSNico Weber GET_CALLER_PC_BP_SP; \ 125217222abSNico Weber ReportGenericError(pc, bp, sp, addr, is_write, size, 0, false); \ 126217222abSNico Weber } \ 127217222abSNico Weber 128217222abSNico Weber ASAN_REPORT_ERROR(load, false, 1) 129217222abSNico Weber ASAN_REPORT_ERROR(load, false, 2) 130217222abSNico Weber ASAN_REPORT_ERROR(load, false, 4) 131217222abSNico Weber ASAN_REPORT_ERROR(load, false, 8) 132217222abSNico Weber ASAN_REPORT_ERROR(load, false, 16) 133217222abSNico Weber ASAN_REPORT_ERROR(store, true, 1) 134217222abSNico Weber ASAN_REPORT_ERROR(store, true, 2) 135217222abSNico Weber ASAN_REPORT_ERROR(store, true, 4) 136217222abSNico Weber ASAN_REPORT_ERROR(store, true, 8) 137217222abSNico Weber ASAN_REPORT_ERROR(store, true, 16) 138217222abSNico Weber 139217222abSNico Weber #define ASAN_REPORT_ERROR_N(type, is_write) \ 140217222abSNico Weber extern "C" NOINLINE INTERFACE_ATTRIBUTE \ 141217222abSNico Weber void __asan_report_ ## type ## _n(uptr addr, uptr size) { \ 142217222abSNico Weber GET_CALLER_PC_BP_SP; \ 143217222abSNico Weber ReportGenericError(pc, bp, sp, addr, is_write, size, 0, true); \ 144217222abSNico Weber } \ 145217222abSNico Weber extern "C" NOINLINE INTERFACE_ATTRIBUTE \ 146217222abSNico Weber void __asan_report_exp_ ## type ## _n(uptr addr, uptr size, u32 exp) { \ 147217222abSNico Weber GET_CALLER_PC_BP_SP; \ 148217222abSNico Weber ReportGenericError(pc, bp, sp, addr, is_write, size, exp, true); \ 149217222abSNico Weber } \ 150217222abSNico Weber extern "C" NOINLINE INTERFACE_ATTRIBUTE \ 151217222abSNico Weber void __asan_report_ ## type ## _n_noabort(uptr addr, uptr size) { \ 152217222abSNico Weber GET_CALLER_PC_BP_SP; \ 153217222abSNico Weber ReportGenericError(pc, bp, sp, addr, is_write, size, 0, false); \ 154217222abSNico Weber } \ 155217222abSNico Weber 156217222abSNico Weber ASAN_REPORT_ERROR_N(load, false) 157217222abSNico Weber ASAN_REPORT_ERROR_N(store, true) 158217222abSNico Weber 159217222abSNico Weber #define ASAN_MEMORY_ACCESS_CALLBACK_BODY(type, is_write, size, exp_arg, fatal) \ 160217222abSNico Weber uptr sp = MEM_TO_SHADOW(addr); \ 161ad56941aSKirill Stoimenov uptr s = size <= ASAN_SHADOW_GRANULARITY ? *reinterpret_cast<u8 *>(sp) \ 162217222abSNico Weber : *reinterpret_cast<u16 *>(sp); \ 163217222abSNico Weber if (UNLIKELY(s)) { \ 164ad56941aSKirill Stoimenov if (UNLIKELY(size >= ASAN_SHADOW_GRANULARITY || \ 165ad56941aSKirill Stoimenov ((s8)((addr & (ASAN_SHADOW_GRANULARITY - 1)) + size - 1)) >= \ 166217222abSNico Weber (s8)s)) { \ 1677de73da8SKirill Stoimenov ReportGenericErrorWrapper(addr, is_write, size, exp_arg, fatal); \ 168217222abSNico Weber } \ 169217222abSNico Weber } 170217222abSNico Weber 171217222abSNico Weber #define ASAN_MEMORY_ACCESS_CALLBACK(type, is_write, size) \ 172217222abSNico Weber extern "C" NOINLINE INTERFACE_ATTRIBUTE \ 173217222abSNico Weber void __asan_##type##size(uptr addr) { \ 174217222abSNico Weber ASAN_MEMORY_ACCESS_CALLBACK_BODY(type, is_write, size, 0, true) \ 175217222abSNico Weber } \ 176217222abSNico Weber extern "C" NOINLINE INTERFACE_ATTRIBUTE \ 177217222abSNico Weber void __asan_exp_##type##size(uptr addr, u32 exp) { \ 178217222abSNico Weber ASAN_MEMORY_ACCESS_CALLBACK_BODY(type, is_write, size, exp, true) \ 179217222abSNico Weber } \ 180217222abSNico Weber extern "C" NOINLINE INTERFACE_ATTRIBUTE \ 181217222abSNico Weber void __asan_##type##size ## _noabort(uptr addr) { \ 182217222abSNico Weber ASAN_MEMORY_ACCESS_CALLBACK_BODY(type, is_write, size, 0, false) \ 183217222abSNico Weber } \ 184217222abSNico Weber 185217222abSNico Weber ASAN_MEMORY_ACCESS_CALLBACK(load, false, 1) 186217222abSNico Weber ASAN_MEMORY_ACCESS_CALLBACK(load, false, 2) 187217222abSNico Weber ASAN_MEMORY_ACCESS_CALLBACK(load, false, 4) 188217222abSNico Weber ASAN_MEMORY_ACCESS_CALLBACK(load, false, 8) 189217222abSNico Weber ASAN_MEMORY_ACCESS_CALLBACK(load, false, 16) 190217222abSNico Weber ASAN_MEMORY_ACCESS_CALLBACK(store, true, 1) 191217222abSNico Weber ASAN_MEMORY_ACCESS_CALLBACK(store, true, 2) 192217222abSNico Weber ASAN_MEMORY_ACCESS_CALLBACK(store, true, 4) 193217222abSNico Weber ASAN_MEMORY_ACCESS_CALLBACK(store, true, 8) 194217222abSNico Weber ASAN_MEMORY_ACCESS_CALLBACK(store, true, 16) 195217222abSNico Weber 196217222abSNico Weber extern "C" 197217222abSNico Weber NOINLINE INTERFACE_ATTRIBUTE 198217222abSNico Weber void __asan_loadN(uptr addr, uptr size) { 19964c929ecSKirill Stoimenov if ((addr = __asan_region_is_poisoned(addr, size))) { 200217222abSNico Weber GET_CALLER_PC_BP_SP; 201217222abSNico Weber ReportGenericError(pc, bp, sp, addr, false, size, 0, true); 202217222abSNico Weber } 203217222abSNico Weber } 204217222abSNico Weber 205217222abSNico Weber extern "C" 206217222abSNico Weber NOINLINE INTERFACE_ATTRIBUTE 207217222abSNico Weber void __asan_exp_loadN(uptr addr, uptr size, u32 exp) { 20864c929ecSKirill Stoimenov if ((addr = __asan_region_is_poisoned(addr, size))) { 209217222abSNico Weber GET_CALLER_PC_BP_SP; 210217222abSNico Weber ReportGenericError(pc, bp, sp, addr, false, size, exp, true); 211217222abSNico Weber } 212217222abSNico Weber } 213217222abSNico Weber 214217222abSNico Weber extern "C" 215217222abSNico Weber NOINLINE INTERFACE_ATTRIBUTE 216217222abSNico Weber void __asan_loadN_noabort(uptr addr, uptr size) { 21764c929ecSKirill Stoimenov if ((addr = __asan_region_is_poisoned(addr, size))) { 218217222abSNico Weber GET_CALLER_PC_BP_SP; 219217222abSNico Weber ReportGenericError(pc, bp, sp, addr, false, size, 0, false); 220217222abSNico Weber } 221217222abSNico Weber } 222217222abSNico Weber 223217222abSNico Weber extern "C" 224217222abSNico Weber NOINLINE INTERFACE_ATTRIBUTE 225217222abSNico Weber void __asan_storeN(uptr addr, uptr size) { 22664c929ecSKirill Stoimenov if ((addr = __asan_region_is_poisoned(addr, size))) { 227217222abSNico Weber GET_CALLER_PC_BP_SP; 228217222abSNico Weber ReportGenericError(pc, bp, sp, addr, true, size, 0, true); 229217222abSNico Weber } 230217222abSNico Weber } 231217222abSNico Weber 232217222abSNico Weber extern "C" 233217222abSNico Weber NOINLINE INTERFACE_ATTRIBUTE 234217222abSNico Weber void __asan_exp_storeN(uptr addr, uptr size, u32 exp) { 23564c929ecSKirill Stoimenov if ((addr = __asan_region_is_poisoned(addr, size))) { 236217222abSNico Weber GET_CALLER_PC_BP_SP; 237217222abSNico Weber ReportGenericError(pc, bp, sp, addr, true, size, exp, true); 238217222abSNico Weber } 239217222abSNico Weber } 240217222abSNico Weber 241217222abSNico Weber extern "C" 242217222abSNico Weber NOINLINE INTERFACE_ATTRIBUTE 243217222abSNico Weber void __asan_storeN_noabort(uptr addr, uptr size) { 24464c929ecSKirill Stoimenov if ((addr = __asan_region_is_poisoned(addr, size))) { 245217222abSNico Weber GET_CALLER_PC_BP_SP; 246217222abSNico Weber ReportGenericError(pc, bp, sp, addr, true, size, 0, false); 247217222abSNico Weber } 248217222abSNico Weber } 249217222abSNico Weber 250217222abSNico Weber // Force the linker to keep the symbols for various ASan interface functions. 251217222abSNico Weber // We want to keep those in the executable in order to let the instrumented 252217222abSNico Weber // dynamic libraries access the symbol even if it is not used by the executable 253217222abSNico Weber // itself. This should help if the build system is removing dead code at link 254217222abSNico Weber // time. 255217222abSNico Weber static NOINLINE void force_interface_symbols() { 256217222abSNico Weber volatile int fake_condition = 0; // prevent dead condition elimination. 257217222abSNico Weber // __asan_report_* functions are noreturn, so we need a switch to prevent 258217222abSNico Weber // the compiler from removing any of them. 259217222abSNico Weber // clang-format off 260217222abSNico Weber switch (fake_condition) { 261217222abSNico Weber case 1: __asan_report_load1(0); break; 262217222abSNico Weber case 2: __asan_report_load2(0); break; 263217222abSNico Weber case 3: __asan_report_load4(0); break; 264217222abSNico Weber case 4: __asan_report_load8(0); break; 265217222abSNico Weber case 5: __asan_report_load16(0); break; 266217222abSNico Weber case 6: __asan_report_load_n(0, 0); break; 267217222abSNico Weber case 7: __asan_report_store1(0); break; 268217222abSNico Weber case 8: __asan_report_store2(0); break; 269217222abSNico Weber case 9: __asan_report_store4(0); break; 270217222abSNico Weber case 10: __asan_report_store8(0); break; 271217222abSNico Weber case 11: __asan_report_store16(0); break; 272217222abSNico Weber case 12: __asan_report_store_n(0, 0); break; 273217222abSNico Weber case 13: __asan_report_exp_load1(0, 0); break; 274217222abSNico Weber case 14: __asan_report_exp_load2(0, 0); break; 275217222abSNico Weber case 15: __asan_report_exp_load4(0, 0); break; 276217222abSNico Weber case 16: __asan_report_exp_load8(0, 0); break; 277217222abSNico Weber case 17: __asan_report_exp_load16(0, 0); break; 278217222abSNico Weber case 18: __asan_report_exp_load_n(0, 0, 0); break; 279217222abSNico Weber case 19: __asan_report_exp_store1(0, 0); break; 280217222abSNico Weber case 20: __asan_report_exp_store2(0, 0); break; 281217222abSNico Weber case 21: __asan_report_exp_store4(0, 0); break; 282217222abSNico Weber case 22: __asan_report_exp_store8(0, 0); break; 283217222abSNico Weber case 23: __asan_report_exp_store16(0, 0); break; 284217222abSNico Weber case 24: __asan_report_exp_store_n(0, 0, 0); break; 285217222abSNico Weber case 25: __asan_register_globals(nullptr, 0); break; 286217222abSNico Weber case 26: __asan_unregister_globals(nullptr, 0); break; 287217222abSNico Weber case 27: __asan_set_death_callback(nullptr); break; 288217222abSNico Weber case 28: __asan_set_error_report_callback(nullptr); break; 289217222abSNico Weber case 29: __asan_handle_no_return(); break; 290217222abSNico Weber case 30: __asan_address_is_poisoned(nullptr); break; 291217222abSNico Weber case 31: __asan_poison_memory_region(nullptr, 0); break; 292217222abSNico Weber case 32: __asan_unpoison_memory_region(nullptr, 0); break; 293217222abSNico Weber case 34: __asan_before_dynamic_init(nullptr); break; 294217222abSNico Weber case 35: __asan_after_dynamic_init(); break; 295217222abSNico Weber case 36: __asan_poison_stack_memory(0, 0); break; 296217222abSNico Weber case 37: __asan_unpoison_stack_memory(0, 0); break; 297217222abSNico Weber case 38: __asan_region_is_poisoned(0, 0); break; 298217222abSNico Weber case 39: __asan_describe_address(0); break; 299217222abSNico Weber case 40: __asan_set_shadow_00(0, 0); break; 3000c35b616SRoy Sundahl case 41: __asan_set_shadow_01(0, 0); break; 3010c35b616SRoy Sundahl case 42: __asan_set_shadow_02(0, 0); break; 3020c35b616SRoy Sundahl case 43: __asan_set_shadow_03(0, 0); break; 3030c35b616SRoy Sundahl case 44: __asan_set_shadow_04(0, 0); break; 3040c35b616SRoy Sundahl case 45: __asan_set_shadow_05(0, 0); break; 3050c35b616SRoy Sundahl case 46: __asan_set_shadow_06(0, 0); break; 3060c35b616SRoy Sundahl case 47: __asan_set_shadow_07(0, 0); break; 3070c35b616SRoy Sundahl case 48: __asan_set_shadow_f1(0, 0); break; 3080c35b616SRoy Sundahl case 49: __asan_set_shadow_f2(0, 0); break; 3090c35b616SRoy Sundahl case 50: __asan_set_shadow_f3(0, 0); break; 3100c35b616SRoy Sundahl case 51: __asan_set_shadow_f5(0, 0); break; 3110c35b616SRoy Sundahl case 52: __asan_set_shadow_f8(0, 0); break; 312217222abSNico Weber } 313217222abSNico Weber // clang-format on 314217222abSNico Weber } 315217222abSNico Weber 316217222abSNico Weber static void asan_atexit() { 317217222abSNico Weber Printf("AddressSanitizer exit stats:\n"); 318217222abSNico Weber __asan_print_accumulated_stats(); 319217222abSNico Weber // Print AsanMappingProfile. 320217222abSNico Weber for (uptr i = 0; i < kAsanMappingProfileSize; i++) { 321217222abSNico Weber if (AsanMappingProfile[i] == 0) continue; 322217222abSNico Weber Printf("asan_mapping.h:%zd -- %zd\n", i, AsanMappingProfile[i]); 323217222abSNico Weber } 324217222abSNico Weber } 325217222abSNico Weber 326217222abSNico Weber static void InitializeHighMemEnd() { 327217222abSNico Weber #if !ASAN_FIXED_MAPPING 328217222abSNico Weber kHighMemEnd = GetMaxUserVirtualAddress(); 329217222abSNico Weber // Increase kHighMemEnd to make sure it's properly 330217222abSNico Weber // aligned together with kHighMemBeg: 331ad56941aSKirill Stoimenov kHighMemEnd |= (GetMmapGranularity() << ASAN_SHADOW_SCALE) - 1; 332217222abSNico Weber #endif // !ASAN_FIXED_MAPPING 333217222abSNico Weber CHECK_EQ((kHighMemBeg % GetMmapGranularity()), 0); 334217222abSNico Weber } 335217222abSNico Weber 336217222abSNico Weber void PrintAddressSpaceLayout() { 337217222abSNico Weber if (kHighMemBeg) { 338217222abSNico Weber Printf("|| `[%p, %p]` || HighMem ||\n", 339217222abSNico Weber (void*)kHighMemBeg, (void*)kHighMemEnd); 340217222abSNico Weber Printf("|| `[%p, %p]` || HighShadow ||\n", 341217222abSNico Weber (void*)kHighShadowBeg, (void*)kHighShadowEnd); 342217222abSNico Weber } 343217222abSNico Weber if (kMidMemBeg) { 344217222abSNico Weber Printf("|| `[%p, %p]` || ShadowGap3 ||\n", 345217222abSNico Weber (void*)kShadowGap3Beg, (void*)kShadowGap3End); 346217222abSNico Weber Printf("|| `[%p, %p]` || MidMem ||\n", 347217222abSNico Weber (void*)kMidMemBeg, (void*)kMidMemEnd); 348217222abSNico Weber Printf("|| `[%p, %p]` || ShadowGap2 ||\n", 349217222abSNico Weber (void*)kShadowGap2Beg, (void*)kShadowGap2End); 350217222abSNico Weber Printf("|| `[%p, %p]` || MidShadow ||\n", 351217222abSNico Weber (void*)kMidShadowBeg, (void*)kMidShadowEnd); 352217222abSNico Weber } 353217222abSNico Weber Printf("|| `[%p, %p]` || ShadowGap ||\n", 354217222abSNico Weber (void*)kShadowGapBeg, (void*)kShadowGapEnd); 355217222abSNico Weber if (kLowShadowBeg) { 356217222abSNico Weber Printf("|| `[%p, %p]` || LowShadow ||\n", 357217222abSNico Weber (void*)kLowShadowBeg, (void*)kLowShadowEnd); 358217222abSNico Weber Printf("|| `[%p, %p]` || LowMem ||\n", 359217222abSNico Weber (void*)kLowMemBeg, (void*)kLowMemEnd); 360217222abSNico Weber } 361217222abSNico Weber Printf("MemToShadow(shadow): %p %p", 362217222abSNico Weber (void*)MEM_TO_SHADOW(kLowShadowBeg), 363217222abSNico Weber (void*)MEM_TO_SHADOW(kLowShadowEnd)); 364217222abSNico Weber if (kHighMemBeg) { 365217222abSNico Weber Printf(" %p %p", 366217222abSNico Weber (void*)MEM_TO_SHADOW(kHighShadowBeg), 367217222abSNico Weber (void*)MEM_TO_SHADOW(kHighShadowEnd)); 368217222abSNico Weber } 369217222abSNico Weber if (kMidMemBeg) { 370217222abSNico Weber Printf(" %p %p", 371217222abSNico Weber (void*)MEM_TO_SHADOW(kMidShadowBeg), 372217222abSNico Weber (void*)MEM_TO_SHADOW(kMidShadowEnd)); 373217222abSNico Weber } 374217222abSNico Weber Printf("\n"); 375217222abSNico Weber Printf("redzone=%zu\n", (uptr)flags()->redzone); 376217222abSNico Weber Printf("max_redzone=%zu\n", (uptr)flags()->max_redzone); 377217222abSNico Weber Printf("quarantine_size_mb=%zuM\n", (uptr)flags()->quarantine_size_mb); 378217222abSNico Weber Printf("thread_local_quarantine_size_kb=%zuK\n", 379217222abSNico Weber (uptr)flags()->thread_local_quarantine_size_kb); 380217222abSNico Weber Printf("malloc_context_size=%zu\n", 381217222abSNico Weber (uptr)common_flags()->malloc_context_size); 382217222abSNico Weber 383ad56941aSKirill Stoimenov Printf("SHADOW_SCALE: %d\n", (int)ASAN_SHADOW_SCALE); 384ad56941aSKirill Stoimenov Printf("SHADOW_GRANULARITY: %d\n", (int)ASAN_SHADOW_GRANULARITY); 385870eee46SVitaly Buka Printf("SHADOW_OFFSET: %p\n", (void *)ASAN_SHADOW_OFFSET); 386ad56941aSKirill Stoimenov CHECK(ASAN_SHADOW_SCALE >= 3 && ASAN_SHADOW_SCALE <= 7); 387217222abSNico Weber if (kMidMemBeg) 388217222abSNico Weber CHECK(kMidShadowBeg > kLowShadowEnd && 389217222abSNico Weber kMidMemBeg > kMidShadowEnd && 390217222abSNico Weber kHighShadowBeg > kMidMemEnd); 391217222abSNico Weber } 392217222abSNico Weber 3939567b33fSVitaly Buka static bool AsanInitInternal() { 3945d6304f0SZachary Johnson if (LIKELY(AsanInited())) 3959567b33fSVitaly Buka return true; 396217222abSNico Weber SanitizerToolName = "AddressSanitizer"; 397217222abSNico Weber 398217222abSNico Weber CacheBinaryName(); 399217222abSNico Weber 400217222abSNico Weber // Initialize flags. This must be done early, because most of the 401217222abSNico Weber // initialization steps look at flags(). 402217222abSNico Weber InitializeFlags(); 403217222abSNico Weber 404ec563c5aSJulian Lettner WaitForDebugger(flags()->sleep_before_init, "before init"); 405ec563c5aSJulian Lettner 406217222abSNico Weber // Stop performing init at this point if we are being loaded via 407217222abSNico Weber // dlopen() and the platform supports it. 408217222abSNico Weber if (SANITIZER_SUPPORTS_INIT_FOR_DLOPEN && UNLIKELY(HandleDlopenInit())) { 409217222abSNico Weber VReport(1, "AddressSanitizer init is being performed for dlopen().\n"); 4109567b33fSVitaly Buka return false; 411217222abSNico Weber } 412217222abSNico Weber 4138443ce56SFangrui Song // Make sure we are not statically linked. 4148443ce56SFangrui Song __interception::DoesNotSupportStaticLinking(); 415217222abSNico Weber AsanCheckIncompatibleRT(); 416217222abSNico Weber AsanCheckDynamicRTPrereqs(); 417217222abSNico Weber AvoidCVE_2016_2143(); 418217222abSNico Weber 419217222abSNico Weber SetCanPoisonMemory(flags()->poison_heap); 420217222abSNico Weber SetMallocContextSize(common_flags()->malloc_context_size); 421217222abSNico Weber 422217222abSNico Weber InitializePlatformExceptionHandlers(); 423217222abSNico Weber 424217222abSNico Weber InitializeHighMemEnd(); 425217222abSNico Weber 426217222abSNico Weber // Install tool-specific callbacks in sanitizer_common. 427217222abSNico Weber AddDieCallback(AsanDie); 4282721e27cSDmitry Vyukov SetCheckUnwindCallback(CheckUnwind); 429217222abSNico Weber SetPrintfAndReportCallback(AppendToErrorMessageBuffer); 430217222abSNico Weber 431217222abSNico Weber __sanitizer_set_report_path(common_flags()->log_path); 432217222abSNico Weber 433e3258b08SVitaly Buka __asan_option_detect_stack_use_after_return = 434e3258b08SVitaly Buka flags()->detect_stack_use_after_return; 435217222abSNico Weber 436217222abSNico Weber __sanitizer::InitializePlatformEarly(); 437217222abSNico Weber 438217222abSNico Weber // Setup internal allocator callback. 439ad56941aSKirill Stoimenov SetLowLevelAllocateMinAlignment(ASAN_SHADOW_GRANULARITY); 440217222abSNico Weber SetLowLevelAllocateCallback(OnLowLevelAllocate); 441217222abSNico Weber 442217222abSNico Weber InitializeAsanInterceptors(); 443e2ed800dSDavid Carlier CheckASLR(); 444217222abSNico Weber 445217222abSNico Weber // Enable system log ("adb logcat") on Android. 446217222abSNico Weber // Doing this before interceptors are initialized crashes in: 447217222abSNico Weber // AsanInitInternal -> android_log_write -> __interceptor_strcmp 448217222abSNico Weber AndroidLogInit(); 449217222abSNico Weber 450217222abSNico Weber ReplaceSystemMalloc(); 451217222abSNico Weber 452217222abSNico Weber DisableCoreDumperIfNecessary(); 453217222abSNico Weber 454217222abSNico Weber InitializeShadowMemory(); 455217222abSNico Weber 456217222abSNico Weber AsanTSDInit(PlatformTSDDtor); 457217222abSNico Weber InstallDeadlySignalHandlers(AsanOnDeadlySignal); 458217222abSNico Weber 459217222abSNico Weber AllocatorOptions allocator_options; 460217222abSNico Weber allocator_options.SetFrom(flags(), common_flags()); 461217222abSNico Weber InitializeAllocator(allocator_options); 462217222abSNico Weber 463bda0a93aSVitaly Buka if (SANITIZER_START_BACKGROUND_THREAD_IN_ASAN_INTERNAL) 464bda0a93aSVitaly Buka MaybeStartBackgroudThread(); 465bda0a93aSVitaly Buka 466217222abSNico Weber // On Linux AsanThread::ThreadStart() calls malloc() that's why asan_inited 467217222abSNico Weber // should be set to 1 prior to initializing the threads. 46803e345b5SVitaly Buka replace_intrin_cached = flags()->replace_intrin; 4693d718d0eSVitaly Buka SetAsanInited(); 470217222abSNico Weber 471217222abSNico Weber if (flags()->atexit) 472217222abSNico Weber Atexit(asan_atexit); 473217222abSNico Weber 474217222abSNico Weber InitializeCoverage(common_flags()->coverage, common_flags()->coverage_dir); 475217222abSNico Weber 476217222abSNico Weber // Now that ASan runtime is (mostly) initialized, deactivate it if 477217222abSNico Weber // necessary, so that it can be re-activated when requested. 478217222abSNico Weber if (flags()->start_deactivated) 479217222abSNico Weber AsanDeactivate(); 480217222abSNico Weber 481217222abSNico Weber // Create main thread. 482217222abSNico Weber AsanThread *main_thread = CreateMainThread(); 483217222abSNico Weber CHECK_EQ(0, main_thread->tid()); 484217222abSNico Weber force_interface_symbols(); // no-op. 485217222abSNico Weber SanitizerInitializeUnwinder(); 486217222abSNico Weber 487f161e84cSNikita Popov if (CAN_SANITIZE_LEAKS) { 488217222abSNico Weber __lsan::InitCommonLsan(); 489fd7ec90aSRoland McGrath InstallAtExitCheckLeaks(); 490f161e84cSNikita Popov } 491217222abSNico Weber 492e065841cSVitaly Buka InstallAtForkHandler(); 493e065841cSVitaly Buka 494217222abSNico Weber #if CAN_SANITIZE_UB 495217222abSNico Weber __ubsan::InitAsPlugin(); 496217222abSNico Weber #endif 497217222abSNico Weber 498217222abSNico Weber InitializeSuppressions(); 499217222abSNico Weber 500217222abSNico Weber if (CAN_SANITIZE_LEAKS) { 501217222abSNico Weber // LateInitialize() calls dlsym, which can allocate an error string buffer 502217222abSNico Weber // in the TLS. Let's ignore the allocation to avoid reporting a leak. 503217222abSNico Weber __lsan::ScopedInterceptorDisabler disabler; 504217222abSNico Weber Symbolizer::LateInitialize(); 505217222abSNico Weber } else { 506217222abSNico Weber Symbolizer::LateInitialize(); 507217222abSNico Weber } 508217222abSNico Weber 509217222abSNico Weber VReport(1, "AddressSanitizer Init done\n"); 510217222abSNico Weber 511ec563c5aSJulian Lettner WaitForDebugger(flags()->sleep_after_init, "after init"); 5129567b33fSVitaly Buka 5139567b33fSVitaly Buka return true; 514217222abSNico Weber } 515217222abSNico Weber 516217222abSNico Weber // Initialize as requested from some part of ASan runtime library (interceptors, 517217222abSNico Weber // allocator, etc). 518217222abSNico Weber void AsanInitFromRtl() { 5199567b33fSVitaly Buka if (LIKELY(AsanInited())) 5209567b33fSVitaly Buka return; 5219567b33fSVitaly Buka SpinMutexLock lock(&asan_inited_mutex); 522217222abSNico Weber AsanInitInternal(); 523217222abSNico Weber } 524217222abSNico Weber 5255aa2f8c9SVitaly Buka bool TryAsanInitFromRtl() { 5269567b33fSVitaly Buka if (LIKELY(AsanInited())) 5275aa2f8c9SVitaly Buka return true; 5289567b33fSVitaly Buka if (!asan_inited_mutex.TryLock()) 5299567b33fSVitaly Buka return false; 5309567b33fSVitaly Buka bool result = AsanInitInternal(); 5319567b33fSVitaly Buka asan_inited_mutex.Unlock(); 5329567b33fSVitaly Buka return result; 5335aa2f8c9SVitaly Buka } 5345aa2f8c9SVitaly Buka 535217222abSNico Weber #if ASAN_DYNAMIC 536217222abSNico Weber // Initialize runtime in case it's LD_PRELOAD-ed into unsanitized executable 537217222abSNico Weber // (and thus normal initializers from .preinit_array or modules haven't run). 538217222abSNico Weber 539217222abSNico Weber class AsanInitializer { 540c0fa6322SVitaly Buka public: 541217222abSNico Weber AsanInitializer() { 542217222abSNico Weber AsanInitFromRtl(); 543217222abSNico Weber } 544217222abSNico Weber }; 545217222abSNico Weber 546217222abSNico Weber static AsanInitializer asan_initializer; 547217222abSNico Weber #endif // ASAN_DYNAMIC 548217222abSNico Weber 549387e94caSRobert Schneider void UnpoisonStack(uptr bottom, uptr top, const char *type) { 550387e94caSRobert Schneider static const uptr kMaxExpectedCleanupSize = 64 << 20; // 64M 551387e94caSRobert Schneider if (top - bottom > kMaxExpectedCleanupSize) { 552387e94caSRobert Schneider static bool reported_warning = false; 553387e94caSRobert Schneider if (reported_warning) 554217222abSNico Weber return; 555387e94caSRobert Schneider reported_warning = true; 556387e94caSRobert Schneider Report( 557387e94caSRobert Schneider "WARNING: ASan is ignoring requested __asan_handle_no_return: " 558387e94caSRobert Schneider "stack type: %s top: %p; bottom %p; size: %p (%zd)\n" 559387e94caSRobert Schneider "False positive error reports may follow\n" 560387e94caSRobert Schneider "For details see " 561387e94caSRobert Schneider "https://github.com/google/sanitizers/issues/189\n", 562629b40daSMartin Liska type, (void *)top, (void *)bottom, (void *)(top - bottom), 563629b40daSMartin Liska top - bottom); 564387e94caSRobert Schneider return; 565387e94caSRobert Schneider } 566ad56941aSKirill Stoimenov PoisonShadow(bottom, RoundUpTo(top - bottom, ASAN_SHADOW_GRANULARITY), 0); 567387e94caSRobert Schneider } 568217222abSNico Weber 569387e94caSRobert Schneider static void UnpoisonDefaultStack() { 570387e94caSRobert Schneider uptr bottom, top; 571387e94caSRobert Schneider 572387e94caSRobert Schneider if (AsanThread *curr_thread = GetCurrentThread()) { 573217222abSNico Weber int local_stack; 574387e94caSRobert Schneider const uptr page_size = GetPageSizeCached(); 575217222abSNico Weber top = curr_thread->stack_top(); 576387e94caSRobert Schneider bottom = ((uptr)&local_stack - page_size) & ~(page_size - 1); 577217222abSNico Weber } else { 578217222abSNico Weber CHECK(!SANITIZER_FUCHSIA); 579217222abSNico Weber // If we haven't seen this thread, try asking the OS for stack bounds. 580*f13b7d0bSVitaly Buka uptr tls_begin, tls_end; 581*f13b7d0bSVitaly Buka GetThreadStackAndTls(/*main=*/false, &bottom, &top, &tls_begin, &tls_end); 582217222abSNico Weber } 583387e94caSRobert Schneider 584387e94caSRobert Schneider UnpoisonStack(bottom, top, "default"); 585217222abSNico Weber } 586387e94caSRobert Schneider 587387e94caSRobert Schneider static void UnpoisonFakeStack() { 588387e94caSRobert Schneider AsanThread *curr_thread = GetCurrentThread(); 5895b0e5055SVitaly Buka if (!curr_thread) 5905b0e5055SVitaly Buka return; 5915b0e5055SVitaly Buka FakeStack *stack = curr_thread->get_fake_stack(); 5925b0e5055SVitaly Buka if (!stack) 5935b0e5055SVitaly Buka return; 5945b0e5055SVitaly Buka stack->HandleNoReturn(); 595217222abSNico Weber } 596217222abSNico Weber 597387e94caSRobert Schneider } // namespace __asan 598387e94caSRobert Schneider 599387e94caSRobert Schneider // ---------------------- Interface ---------------- {{{1 600387e94caSRobert Schneider using namespace __asan; 601387e94caSRobert Schneider 602387e94caSRobert Schneider void NOINLINE __asan_handle_no_return() { 6039567b33fSVitaly Buka if (UNLIKELY(!AsanInited())) 604387e94caSRobert Schneider return; 605387e94caSRobert Schneider 606387e94caSRobert Schneider if (!PlatformUnpoisonStacks()) 607387e94caSRobert Schneider UnpoisonDefaultStack(); 608387e94caSRobert Schneider 609387e94caSRobert Schneider UnpoisonFakeStack(); 610387e94caSRobert Schneider } 611387e94caSRobert Schneider 612217222abSNico Weber extern "C" void *__asan_extra_spill_area() { 613217222abSNico Weber AsanThread *t = GetCurrentThread(); 614217222abSNico Weber CHECK(t); 615217222abSNico Weber return t->extra_spill_area(); 616217222abSNico Weber } 617217222abSNico Weber 618217222abSNico Weber void __asan_handle_vfork(void *sp) { 619217222abSNico Weber AsanThread *t = GetCurrentThread(); 620217222abSNico Weber CHECK(t); 621217222abSNico Weber uptr bottom = t->stack_bottom(); 622217222abSNico Weber PoisonShadow(bottom, (uptr)sp - bottom, 0); 623217222abSNico Weber } 624217222abSNico Weber 625217222abSNico Weber void NOINLINE __asan_set_death_callback(void (*callback)(void)) { 626217222abSNico Weber SetUserDieCallback(callback); 627217222abSNico Weber } 628217222abSNico Weber 629217222abSNico Weber // Initialize as requested from instrumented application code. 630217222abSNico Weber // We use this call as a trigger to wake up ASan from deactivated state. 631217222abSNico Weber void __asan_init() { 632217222abSNico Weber AsanActivate(); 6339567b33fSVitaly Buka AsanInitFromRtl(); 634217222abSNico Weber } 635217222abSNico Weber 636217222abSNico Weber void __asan_version_mismatch_check() { 637217222abSNico Weber // Do nothing. 638217222abSNico Weber } 639