1*68d75effSDimitry Andric //===-- asan_rtl.cpp ------------------------------------------------------===// 2*68d75effSDimitry Andric // 3*68d75effSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*68d75effSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*68d75effSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*68d75effSDimitry Andric // 7*68d75effSDimitry Andric //===----------------------------------------------------------------------===// 8*68d75effSDimitry Andric // 9*68d75effSDimitry Andric // This file is a part of AddressSanitizer, an address sanity checker. 10*68d75effSDimitry Andric // 11*68d75effSDimitry Andric // Main file of the ASan run-time library. 12*68d75effSDimitry Andric //===----------------------------------------------------------------------===// 13*68d75effSDimitry Andric 14*68d75effSDimitry Andric #include "asan_activation.h" 15*68d75effSDimitry Andric #include "asan_allocator.h" 16*68d75effSDimitry Andric #include "asan_interceptors.h" 17*68d75effSDimitry Andric #include "asan_interface_internal.h" 18*68d75effSDimitry Andric #include "asan_internal.h" 19*68d75effSDimitry Andric #include "asan_mapping.h" 20*68d75effSDimitry Andric #include "asan_poisoning.h" 21*68d75effSDimitry Andric #include "asan_report.h" 22*68d75effSDimitry Andric #include "asan_stack.h" 23*68d75effSDimitry Andric #include "asan_stats.h" 24*68d75effSDimitry Andric #include "asan_suppressions.h" 25*68d75effSDimitry Andric #include "asan_thread.h" 26*68d75effSDimitry Andric #include "sanitizer_common/sanitizer_atomic.h" 27*68d75effSDimitry Andric #include "sanitizer_common/sanitizer_flags.h" 28*68d75effSDimitry Andric #include "sanitizer_common/sanitizer_libc.h" 29*68d75effSDimitry Andric #include "sanitizer_common/sanitizer_symbolizer.h" 30*68d75effSDimitry Andric #include "lsan/lsan_common.h" 31*68d75effSDimitry Andric #include "ubsan/ubsan_init.h" 32*68d75effSDimitry Andric #include "ubsan/ubsan_platform.h" 33*68d75effSDimitry Andric 34*68d75effSDimitry Andric uptr __asan_shadow_memory_dynamic_address; // Global interface symbol. 35*68d75effSDimitry Andric int __asan_option_detect_stack_use_after_return; // Global interface symbol. 36*68d75effSDimitry Andric uptr *__asan_test_only_reported_buggy_pointer; // Used only for testing asan. 37*68d75effSDimitry Andric 38*68d75effSDimitry Andric namespace __asan { 39*68d75effSDimitry Andric 40*68d75effSDimitry Andric uptr AsanMappingProfile[kAsanMappingProfileSize]; 41*68d75effSDimitry Andric 42*68d75effSDimitry Andric static void AsanDie() { 43*68d75effSDimitry Andric static atomic_uint32_t num_calls; 44*68d75effSDimitry Andric if (atomic_fetch_add(&num_calls, 1, memory_order_relaxed) != 0) { 45*68d75effSDimitry Andric // Don't die twice - run a busy loop. 46*68d75effSDimitry Andric while (1) { } 47*68d75effSDimitry Andric } 48*68d75effSDimitry Andric if (common_flags()->print_module_map >= 1) PrintModuleMap(); 49*68d75effSDimitry Andric if (flags()->sleep_before_dying) { 50*68d75effSDimitry Andric Report("Sleeping for %d second(s)\n", flags()->sleep_before_dying); 51*68d75effSDimitry Andric SleepForSeconds(flags()->sleep_before_dying); 52*68d75effSDimitry Andric } 53*68d75effSDimitry Andric if (flags()->unmap_shadow_on_exit) { 54*68d75effSDimitry Andric if (kMidMemBeg) { 55*68d75effSDimitry Andric UnmapOrDie((void*)kLowShadowBeg, kMidMemBeg - kLowShadowBeg); 56*68d75effSDimitry Andric UnmapOrDie((void*)kMidMemEnd, kHighShadowEnd - kMidMemEnd); 57*68d75effSDimitry Andric } else { 58*68d75effSDimitry Andric if (kHighShadowEnd) 59*68d75effSDimitry Andric UnmapOrDie((void*)kLowShadowBeg, kHighShadowEnd - kLowShadowBeg); 60*68d75effSDimitry Andric } 61*68d75effSDimitry Andric } 62*68d75effSDimitry Andric } 63*68d75effSDimitry Andric 64*68d75effSDimitry Andric static void AsanCheckFailed(const char *file, int line, const char *cond, 65*68d75effSDimitry Andric u64 v1, u64 v2) { 66*68d75effSDimitry Andric Report("AddressSanitizer CHECK failed: %s:%d \"%s\" (0x%zx, 0x%zx)\n", file, 67*68d75effSDimitry Andric line, cond, (uptr)v1, (uptr)v2); 68*68d75effSDimitry Andric 69*68d75effSDimitry Andric // Print a stack trace the first time we come here. Otherwise, we probably 70*68d75effSDimitry Andric // failed a CHECK during symbolization. 71*68d75effSDimitry Andric static atomic_uint32_t num_calls; 72*68d75effSDimitry Andric if (atomic_fetch_add(&num_calls, 1, memory_order_relaxed) == 0) { 73*68d75effSDimitry Andric PRINT_CURRENT_STACK_CHECK(); 74*68d75effSDimitry Andric } 75*68d75effSDimitry Andric 76*68d75effSDimitry Andric Die(); 77*68d75effSDimitry Andric } 78*68d75effSDimitry Andric 79*68d75effSDimitry Andric // -------------------------- Globals --------------------- {{{1 80*68d75effSDimitry Andric int asan_inited; 81*68d75effSDimitry Andric bool asan_init_is_running; 82*68d75effSDimitry Andric 83*68d75effSDimitry Andric #if !ASAN_FIXED_MAPPING 84*68d75effSDimitry Andric uptr kHighMemEnd, kMidMemBeg, kMidMemEnd; 85*68d75effSDimitry Andric #endif 86*68d75effSDimitry Andric 87*68d75effSDimitry Andric // -------------------------- Misc ---------------- {{{1 88*68d75effSDimitry Andric void ShowStatsAndAbort() { 89*68d75effSDimitry Andric __asan_print_accumulated_stats(); 90*68d75effSDimitry Andric Die(); 91*68d75effSDimitry Andric } 92*68d75effSDimitry Andric 93*68d75effSDimitry Andric // --------------- LowLevelAllocateCallbac ---------- {{{1 94*68d75effSDimitry Andric static void OnLowLevelAllocate(uptr ptr, uptr size) { 95*68d75effSDimitry Andric PoisonShadow(ptr, size, kAsanInternalHeapMagic); 96*68d75effSDimitry Andric } 97*68d75effSDimitry Andric 98*68d75effSDimitry Andric // -------------------------- Run-time entry ------------------- {{{1 99*68d75effSDimitry Andric // exported functions 100*68d75effSDimitry Andric #define ASAN_REPORT_ERROR(type, is_write, size) \ 101*68d75effSDimitry Andric extern "C" NOINLINE INTERFACE_ATTRIBUTE \ 102*68d75effSDimitry Andric void __asan_report_ ## type ## size(uptr addr) { \ 103*68d75effSDimitry Andric GET_CALLER_PC_BP_SP; \ 104*68d75effSDimitry Andric ReportGenericError(pc, bp, sp, addr, is_write, size, 0, true); \ 105*68d75effSDimitry Andric } \ 106*68d75effSDimitry Andric extern "C" NOINLINE INTERFACE_ATTRIBUTE \ 107*68d75effSDimitry Andric void __asan_report_exp_ ## type ## size(uptr addr, u32 exp) { \ 108*68d75effSDimitry Andric GET_CALLER_PC_BP_SP; \ 109*68d75effSDimitry Andric ReportGenericError(pc, bp, sp, addr, is_write, size, exp, true); \ 110*68d75effSDimitry Andric } \ 111*68d75effSDimitry Andric extern "C" NOINLINE INTERFACE_ATTRIBUTE \ 112*68d75effSDimitry Andric void __asan_report_ ## type ## size ## _noabort(uptr addr) { \ 113*68d75effSDimitry Andric GET_CALLER_PC_BP_SP; \ 114*68d75effSDimitry Andric ReportGenericError(pc, bp, sp, addr, is_write, size, 0, false); \ 115*68d75effSDimitry Andric } \ 116*68d75effSDimitry Andric 117*68d75effSDimitry Andric ASAN_REPORT_ERROR(load, false, 1) 118*68d75effSDimitry Andric ASAN_REPORT_ERROR(load, false, 2) 119*68d75effSDimitry Andric ASAN_REPORT_ERROR(load, false, 4) 120*68d75effSDimitry Andric ASAN_REPORT_ERROR(load, false, 8) 121*68d75effSDimitry Andric ASAN_REPORT_ERROR(load, false, 16) 122*68d75effSDimitry Andric ASAN_REPORT_ERROR(store, true, 1) 123*68d75effSDimitry Andric ASAN_REPORT_ERROR(store, true, 2) 124*68d75effSDimitry Andric ASAN_REPORT_ERROR(store, true, 4) 125*68d75effSDimitry Andric ASAN_REPORT_ERROR(store, true, 8) 126*68d75effSDimitry Andric ASAN_REPORT_ERROR(store, true, 16) 127*68d75effSDimitry Andric 128*68d75effSDimitry Andric #define ASAN_REPORT_ERROR_N(type, is_write) \ 129*68d75effSDimitry Andric extern "C" NOINLINE INTERFACE_ATTRIBUTE \ 130*68d75effSDimitry Andric void __asan_report_ ## type ## _n(uptr addr, uptr size) { \ 131*68d75effSDimitry Andric GET_CALLER_PC_BP_SP; \ 132*68d75effSDimitry Andric ReportGenericError(pc, bp, sp, addr, is_write, size, 0, true); \ 133*68d75effSDimitry Andric } \ 134*68d75effSDimitry Andric extern "C" NOINLINE INTERFACE_ATTRIBUTE \ 135*68d75effSDimitry Andric void __asan_report_exp_ ## type ## _n(uptr addr, uptr size, u32 exp) { \ 136*68d75effSDimitry Andric GET_CALLER_PC_BP_SP; \ 137*68d75effSDimitry Andric ReportGenericError(pc, bp, sp, addr, is_write, size, exp, true); \ 138*68d75effSDimitry Andric } \ 139*68d75effSDimitry Andric extern "C" NOINLINE INTERFACE_ATTRIBUTE \ 140*68d75effSDimitry Andric void __asan_report_ ## type ## _n_noabort(uptr addr, uptr size) { \ 141*68d75effSDimitry Andric GET_CALLER_PC_BP_SP; \ 142*68d75effSDimitry Andric ReportGenericError(pc, bp, sp, addr, is_write, size, 0, false); \ 143*68d75effSDimitry Andric } \ 144*68d75effSDimitry Andric 145*68d75effSDimitry Andric ASAN_REPORT_ERROR_N(load, false) 146*68d75effSDimitry Andric ASAN_REPORT_ERROR_N(store, true) 147*68d75effSDimitry Andric 148*68d75effSDimitry Andric #define ASAN_MEMORY_ACCESS_CALLBACK_BODY(type, is_write, size, exp_arg, fatal) \ 149*68d75effSDimitry Andric if (SANITIZER_MYRIAD2 && !AddrIsInMem(addr) && !AddrIsInShadow(addr)) \ 150*68d75effSDimitry Andric return; \ 151*68d75effSDimitry Andric uptr sp = MEM_TO_SHADOW(addr); \ 152*68d75effSDimitry Andric uptr s = size <= SHADOW_GRANULARITY ? *reinterpret_cast<u8 *>(sp) \ 153*68d75effSDimitry Andric : *reinterpret_cast<u16 *>(sp); \ 154*68d75effSDimitry Andric if (UNLIKELY(s)) { \ 155*68d75effSDimitry Andric if (UNLIKELY(size >= SHADOW_GRANULARITY || \ 156*68d75effSDimitry Andric ((s8)((addr & (SHADOW_GRANULARITY - 1)) + size - 1)) >= \ 157*68d75effSDimitry Andric (s8)s)) { \ 158*68d75effSDimitry Andric if (__asan_test_only_reported_buggy_pointer) { \ 159*68d75effSDimitry Andric *__asan_test_only_reported_buggy_pointer = addr; \ 160*68d75effSDimitry Andric } else { \ 161*68d75effSDimitry Andric GET_CALLER_PC_BP_SP; \ 162*68d75effSDimitry Andric ReportGenericError(pc, bp, sp, addr, is_write, size, exp_arg, \ 163*68d75effSDimitry Andric fatal); \ 164*68d75effSDimitry Andric } \ 165*68d75effSDimitry Andric } \ 166*68d75effSDimitry Andric } 167*68d75effSDimitry Andric 168*68d75effSDimitry Andric #define ASAN_MEMORY_ACCESS_CALLBACK(type, is_write, size) \ 169*68d75effSDimitry Andric extern "C" NOINLINE INTERFACE_ATTRIBUTE \ 170*68d75effSDimitry Andric void __asan_##type##size(uptr addr) { \ 171*68d75effSDimitry Andric ASAN_MEMORY_ACCESS_CALLBACK_BODY(type, is_write, size, 0, true) \ 172*68d75effSDimitry Andric } \ 173*68d75effSDimitry Andric extern "C" NOINLINE INTERFACE_ATTRIBUTE \ 174*68d75effSDimitry Andric void __asan_exp_##type##size(uptr addr, u32 exp) { \ 175*68d75effSDimitry Andric ASAN_MEMORY_ACCESS_CALLBACK_BODY(type, is_write, size, exp, true) \ 176*68d75effSDimitry Andric } \ 177*68d75effSDimitry Andric extern "C" NOINLINE INTERFACE_ATTRIBUTE \ 178*68d75effSDimitry Andric void __asan_##type##size ## _noabort(uptr addr) { \ 179*68d75effSDimitry Andric ASAN_MEMORY_ACCESS_CALLBACK_BODY(type, is_write, size, 0, false) \ 180*68d75effSDimitry Andric } \ 181*68d75effSDimitry Andric 182*68d75effSDimitry Andric ASAN_MEMORY_ACCESS_CALLBACK(load, false, 1) 183*68d75effSDimitry Andric ASAN_MEMORY_ACCESS_CALLBACK(load, false, 2) 184*68d75effSDimitry Andric ASAN_MEMORY_ACCESS_CALLBACK(load, false, 4) 185*68d75effSDimitry Andric ASAN_MEMORY_ACCESS_CALLBACK(load, false, 8) 186*68d75effSDimitry Andric ASAN_MEMORY_ACCESS_CALLBACK(load, false, 16) 187*68d75effSDimitry Andric ASAN_MEMORY_ACCESS_CALLBACK(store, true, 1) 188*68d75effSDimitry Andric ASAN_MEMORY_ACCESS_CALLBACK(store, true, 2) 189*68d75effSDimitry Andric ASAN_MEMORY_ACCESS_CALLBACK(store, true, 4) 190*68d75effSDimitry Andric ASAN_MEMORY_ACCESS_CALLBACK(store, true, 8) 191*68d75effSDimitry Andric ASAN_MEMORY_ACCESS_CALLBACK(store, true, 16) 192*68d75effSDimitry Andric 193*68d75effSDimitry Andric extern "C" 194*68d75effSDimitry Andric NOINLINE INTERFACE_ATTRIBUTE 195*68d75effSDimitry Andric void __asan_loadN(uptr addr, uptr size) { 196*68d75effSDimitry Andric if (__asan_region_is_poisoned(addr, size)) { 197*68d75effSDimitry Andric GET_CALLER_PC_BP_SP; 198*68d75effSDimitry Andric ReportGenericError(pc, bp, sp, addr, false, size, 0, true); 199*68d75effSDimitry Andric } 200*68d75effSDimitry Andric } 201*68d75effSDimitry Andric 202*68d75effSDimitry Andric extern "C" 203*68d75effSDimitry Andric NOINLINE INTERFACE_ATTRIBUTE 204*68d75effSDimitry Andric void __asan_exp_loadN(uptr addr, uptr size, u32 exp) { 205*68d75effSDimitry Andric if (__asan_region_is_poisoned(addr, size)) { 206*68d75effSDimitry Andric GET_CALLER_PC_BP_SP; 207*68d75effSDimitry Andric ReportGenericError(pc, bp, sp, addr, false, size, exp, true); 208*68d75effSDimitry Andric } 209*68d75effSDimitry Andric } 210*68d75effSDimitry Andric 211*68d75effSDimitry Andric extern "C" 212*68d75effSDimitry Andric NOINLINE INTERFACE_ATTRIBUTE 213*68d75effSDimitry Andric void __asan_loadN_noabort(uptr addr, uptr size) { 214*68d75effSDimitry Andric if (__asan_region_is_poisoned(addr, size)) { 215*68d75effSDimitry Andric GET_CALLER_PC_BP_SP; 216*68d75effSDimitry Andric ReportGenericError(pc, bp, sp, addr, false, size, 0, false); 217*68d75effSDimitry Andric } 218*68d75effSDimitry Andric } 219*68d75effSDimitry Andric 220*68d75effSDimitry Andric extern "C" 221*68d75effSDimitry Andric NOINLINE INTERFACE_ATTRIBUTE 222*68d75effSDimitry Andric void __asan_storeN(uptr addr, uptr size) { 223*68d75effSDimitry Andric if (__asan_region_is_poisoned(addr, size)) { 224*68d75effSDimitry Andric GET_CALLER_PC_BP_SP; 225*68d75effSDimitry Andric ReportGenericError(pc, bp, sp, addr, true, size, 0, true); 226*68d75effSDimitry Andric } 227*68d75effSDimitry Andric } 228*68d75effSDimitry Andric 229*68d75effSDimitry Andric extern "C" 230*68d75effSDimitry Andric NOINLINE INTERFACE_ATTRIBUTE 231*68d75effSDimitry Andric void __asan_exp_storeN(uptr addr, uptr size, u32 exp) { 232*68d75effSDimitry Andric if (__asan_region_is_poisoned(addr, size)) { 233*68d75effSDimitry Andric GET_CALLER_PC_BP_SP; 234*68d75effSDimitry Andric ReportGenericError(pc, bp, sp, addr, true, size, exp, true); 235*68d75effSDimitry Andric } 236*68d75effSDimitry Andric } 237*68d75effSDimitry Andric 238*68d75effSDimitry Andric extern "C" 239*68d75effSDimitry Andric NOINLINE INTERFACE_ATTRIBUTE 240*68d75effSDimitry Andric void __asan_storeN_noabort(uptr addr, uptr size) { 241*68d75effSDimitry Andric if (__asan_region_is_poisoned(addr, size)) { 242*68d75effSDimitry Andric GET_CALLER_PC_BP_SP; 243*68d75effSDimitry Andric ReportGenericError(pc, bp, sp, addr, true, size, 0, false); 244*68d75effSDimitry Andric } 245*68d75effSDimitry Andric } 246*68d75effSDimitry Andric 247*68d75effSDimitry Andric // Force the linker to keep the symbols for various ASan interface functions. 248*68d75effSDimitry Andric // We want to keep those in the executable in order to let the instrumented 249*68d75effSDimitry Andric // dynamic libraries access the symbol even if it is not used by the executable 250*68d75effSDimitry Andric // itself. This should help if the build system is removing dead code at link 251*68d75effSDimitry Andric // time. 252*68d75effSDimitry Andric static NOINLINE void force_interface_symbols() { 253*68d75effSDimitry Andric volatile int fake_condition = 0; // prevent dead condition elimination. 254*68d75effSDimitry Andric // __asan_report_* functions are noreturn, so we need a switch to prevent 255*68d75effSDimitry Andric // the compiler from removing any of them. 256*68d75effSDimitry Andric // clang-format off 257*68d75effSDimitry Andric switch (fake_condition) { 258*68d75effSDimitry Andric case 1: __asan_report_load1(0); break; 259*68d75effSDimitry Andric case 2: __asan_report_load2(0); break; 260*68d75effSDimitry Andric case 3: __asan_report_load4(0); break; 261*68d75effSDimitry Andric case 4: __asan_report_load8(0); break; 262*68d75effSDimitry Andric case 5: __asan_report_load16(0); break; 263*68d75effSDimitry Andric case 6: __asan_report_load_n(0, 0); break; 264*68d75effSDimitry Andric case 7: __asan_report_store1(0); break; 265*68d75effSDimitry Andric case 8: __asan_report_store2(0); break; 266*68d75effSDimitry Andric case 9: __asan_report_store4(0); break; 267*68d75effSDimitry Andric case 10: __asan_report_store8(0); break; 268*68d75effSDimitry Andric case 11: __asan_report_store16(0); break; 269*68d75effSDimitry Andric case 12: __asan_report_store_n(0, 0); break; 270*68d75effSDimitry Andric case 13: __asan_report_exp_load1(0, 0); break; 271*68d75effSDimitry Andric case 14: __asan_report_exp_load2(0, 0); break; 272*68d75effSDimitry Andric case 15: __asan_report_exp_load4(0, 0); break; 273*68d75effSDimitry Andric case 16: __asan_report_exp_load8(0, 0); break; 274*68d75effSDimitry Andric case 17: __asan_report_exp_load16(0, 0); break; 275*68d75effSDimitry Andric case 18: __asan_report_exp_load_n(0, 0, 0); break; 276*68d75effSDimitry Andric case 19: __asan_report_exp_store1(0, 0); break; 277*68d75effSDimitry Andric case 20: __asan_report_exp_store2(0, 0); break; 278*68d75effSDimitry Andric case 21: __asan_report_exp_store4(0, 0); break; 279*68d75effSDimitry Andric case 22: __asan_report_exp_store8(0, 0); break; 280*68d75effSDimitry Andric case 23: __asan_report_exp_store16(0, 0); break; 281*68d75effSDimitry Andric case 24: __asan_report_exp_store_n(0, 0, 0); break; 282*68d75effSDimitry Andric case 25: __asan_register_globals(nullptr, 0); break; 283*68d75effSDimitry Andric case 26: __asan_unregister_globals(nullptr, 0); break; 284*68d75effSDimitry Andric case 27: __asan_set_death_callback(nullptr); break; 285*68d75effSDimitry Andric case 28: __asan_set_error_report_callback(nullptr); break; 286*68d75effSDimitry Andric case 29: __asan_handle_no_return(); break; 287*68d75effSDimitry Andric case 30: __asan_address_is_poisoned(nullptr); break; 288*68d75effSDimitry Andric case 31: __asan_poison_memory_region(nullptr, 0); break; 289*68d75effSDimitry Andric case 32: __asan_unpoison_memory_region(nullptr, 0); break; 290*68d75effSDimitry Andric case 34: __asan_before_dynamic_init(nullptr); break; 291*68d75effSDimitry Andric case 35: __asan_after_dynamic_init(); break; 292*68d75effSDimitry Andric case 36: __asan_poison_stack_memory(0, 0); break; 293*68d75effSDimitry Andric case 37: __asan_unpoison_stack_memory(0, 0); break; 294*68d75effSDimitry Andric case 38: __asan_region_is_poisoned(0, 0); break; 295*68d75effSDimitry Andric case 39: __asan_describe_address(0); break; 296*68d75effSDimitry Andric case 40: __asan_set_shadow_00(0, 0); break; 297*68d75effSDimitry Andric case 41: __asan_set_shadow_f1(0, 0); break; 298*68d75effSDimitry Andric case 42: __asan_set_shadow_f2(0, 0); break; 299*68d75effSDimitry Andric case 43: __asan_set_shadow_f3(0, 0); break; 300*68d75effSDimitry Andric case 44: __asan_set_shadow_f5(0, 0); break; 301*68d75effSDimitry Andric case 45: __asan_set_shadow_f8(0, 0); break; 302*68d75effSDimitry Andric } 303*68d75effSDimitry Andric // clang-format on 304*68d75effSDimitry Andric } 305*68d75effSDimitry Andric 306*68d75effSDimitry Andric static void asan_atexit() { 307*68d75effSDimitry Andric Printf("AddressSanitizer exit stats:\n"); 308*68d75effSDimitry Andric __asan_print_accumulated_stats(); 309*68d75effSDimitry Andric // Print AsanMappingProfile. 310*68d75effSDimitry Andric for (uptr i = 0; i < kAsanMappingProfileSize; i++) { 311*68d75effSDimitry Andric if (AsanMappingProfile[i] == 0) continue; 312*68d75effSDimitry Andric Printf("asan_mapping.h:%zd -- %zd\n", i, AsanMappingProfile[i]); 313*68d75effSDimitry Andric } 314*68d75effSDimitry Andric } 315*68d75effSDimitry Andric 316*68d75effSDimitry Andric static void InitializeHighMemEnd() { 317*68d75effSDimitry Andric #if !SANITIZER_MYRIAD2 318*68d75effSDimitry Andric #if !ASAN_FIXED_MAPPING 319*68d75effSDimitry Andric kHighMemEnd = GetMaxUserVirtualAddress(); 320*68d75effSDimitry Andric // Increase kHighMemEnd to make sure it's properly 321*68d75effSDimitry Andric // aligned together with kHighMemBeg: 322*68d75effSDimitry Andric kHighMemEnd |= SHADOW_GRANULARITY * GetMmapGranularity() - 1; 323*68d75effSDimitry Andric #endif // !ASAN_FIXED_MAPPING 324*68d75effSDimitry Andric CHECK_EQ((kHighMemBeg % GetMmapGranularity()), 0); 325*68d75effSDimitry Andric #endif // !SANITIZER_MYRIAD2 326*68d75effSDimitry Andric } 327*68d75effSDimitry Andric 328*68d75effSDimitry Andric void PrintAddressSpaceLayout() { 329*68d75effSDimitry Andric if (kHighMemBeg) { 330*68d75effSDimitry Andric Printf("|| `[%p, %p]` || HighMem ||\n", 331*68d75effSDimitry Andric (void*)kHighMemBeg, (void*)kHighMemEnd); 332*68d75effSDimitry Andric Printf("|| `[%p, %p]` || HighShadow ||\n", 333*68d75effSDimitry Andric (void*)kHighShadowBeg, (void*)kHighShadowEnd); 334*68d75effSDimitry Andric } 335*68d75effSDimitry Andric if (kMidMemBeg) { 336*68d75effSDimitry Andric Printf("|| `[%p, %p]` || ShadowGap3 ||\n", 337*68d75effSDimitry Andric (void*)kShadowGap3Beg, (void*)kShadowGap3End); 338*68d75effSDimitry Andric Printf("|| `[%p, %p]` || MidMem ||\n", 339*68d75effSDimitry Andric (void*)kMidMemBeg, (void*)kMidMemEnd); 340*68d75effSDimitry Andric Printf("|| `[%p, %p]` || ShadowGap2 ||\n", 341*68d75effSDimitry Andric (void*)kShadowGap2Beg, (void*)kShadowGap2End); 342*68d75effSDimitry Andric Printf("|| `[%p, %p]` || MidShadow ||\n", 343*68d75effSDimitry Andric (void*)kMidShadowBeg, (void*)kMidShadowEnd); 344*68d75effSDimitry Andric } 345*68d75effSDimitry Andric Printf("|| `[%p, %p]` || ShadowGap ||\n", 346*68d75effSDimitry Andric (void*)kShadowGapBeg, (void*)kShadowGapEnd); 347*68d75effSDimitry Andric if (kLowShadowBeg) { 348*68d75effSDimitry Andric Printf("|| `[%p, %p]` || LowShadow ||\n", 349*68d75effSDimitry Andric (void*)kLowShadowBeg, (void*)kLowShadowEnd); 350*68d75effSDimitry Andric Printf("|| `[%p, %p]` || LowMem ||\n", 351*68d75effSDimitry Andric (void*)kLowMemBeg, (void*)kLowMemEnd); 352*68d75effSDimitry Andric } 353*68d75effSDimitry Andric Printf("MemToShadow(shadow): %p %p", 354*68d75effSDimitry Andric (void*)MEM_TO_SHADOW(kLowShadowBeg), 355*68d75effSDimitry Andric (void*)MEM_TO_SHADOW(kLowShadowEnd)); 356*68d75effSDimitry Andric if (kHighMemBeg) { 357*68d75effSDimitry Andric Printf(" %p %p", 358*68d75effSDimitry Andric (void*)MEM_TO_SHADOW(kHighShadowBeg), 359*68d75effSDimitry Andric (void*)MEM_TO_SHADOW(kHighShadowEnd)); 360*68d75effSDimitry Andric } 361*68d75effSDimitry Andric if (kMidMemBeg) { 362*68d75effSDimitry Andric Printf(" %p %p", 363*68d75effSDimitry Andric (void*)MEM_TO_SHADOW(kMidShadowBeg), 364*68d75effSDimitry Andric (void*)MEM_TO_SHADOW(kMidShadowEnd)); 365*68d75effSDimitry Andric } 366*68d75effSDimitry Andric Printf("\n"); 367*68d75effSDimitry Andric Printf("redzone=%zu\n", (uptr)flags()->redzone); 368*68d75effSDimitry Andric Printf("max_redzone=%zu\n", (uptr)flags()->max_redzone); 369*68d75effSDimitry Andric Printf("quarantine_size_mb=%zuM\n", (uptr)flags()->quarantine_size_mb); 370*68d75effSDimitry Andric Printf("thread_local_quarantine_size_kb=%zuK\n", 371*68d75effSDimitry Andric (uptr)flags()->thread_local_quarantine_size_kb); 372*68d75effSDimitry Andric Printf("malloc_context_size=%zu\n", 373*68d75effSDimitry Andric (uptr)common_flags()->malloc_context_size); 374*68d75effSDimitry Andric 375*68d75effSDimitry Andric Printf("SHADOW_SCALE: %d\n", (int)SHADOW_SCALE); 376*68d75effSDimitry Andric Printf("SHADOW_GRANULARITY: %d\n", (int)SHADOW_GRANULARITY); 377*68d75effSDimitry Andric Printf("SHADOW_OFFSET: 0x%zx\n", (uptr)SHADOW_OFFSET); 378*68d75effSDimitry Andric CHECK(SHADOW_SCALE >= 3 && SHADOW_SCALE <= 7); 379*68d75effSDimitry Andric if (kMidMemBeg) 380*68d75effSDimitry Andric CHECK(kMidShadowBeg > kLowShadowEnd && 381*68d75effSDimitry Andric kMidMemBeg > kMidShadowEnd && 382*68d75effSDimitry Andric kHighShadowBeg > kMidMemEnd); 383*68d75effSDimitry Andric } 384*68d75effSDimitry Andric 385*68d75effSDimitry Andric #if defined(__thumb__) && defined(__linux__) 386*68d75effSDimitry Andric #define START_BACKGROUND_THREAD_IN_ASAN_INTERNAL 387*68d75effSDimitry Andric #endif 388*68d75effSDimitry Andric 389*68d75effSDimitry Andric #ifndef START_BACKGROUND_THREAD_IN_ASAN_INTERNAL 390*68d75effSDimitry Andric static bool UNUSED __local_asan_dyninit = [] { 391*68d75effSDimitry Andric MaybeStartBackgroudThread(); 392*68d75effSDimitry Andric SetSoftRssLimitExceededCallback(AsanSoftRssLimitExceededCallback); 393*68d75effSDimitry Andric 394*68d75effSDimitry Andric return false; 395*68d75effSDimitry Andric }(); 396*68d75effSDimitry Andric #endif 397*68d75effSDimitry Andric 398*68d75effSDimitry Andric static void AsanInitInternal() { 399*68d75effSDimitry Andric if (LIKELY(asan_inited)) return; 400*68d75effSDimitry Andric SanitizerToolName = "AddressSanitizer"; 401*68d75effSDimitry Andric CHECK(!asan_init_is_running && "ASan init calls itself!"); 402*68d75effSDimitry Andric asan_init_is_running = true; 403*68d75effSDimitry Andric 404*68d75effSDimitry Andric CacheBinaryName(); 405*68d75effSDimitry Andric 406*68d75effSDimitry Andric // Initialize flags. This must be done early, because most of the 407*68d75effSDimitry Andric // initialization steps look at flags(). 408*68d75effSDimitry Andric InitializeFlags(); 409*68d75effSDimitry Andric 410*68d75effSDimitry Andric // Stop performing init at this point if we are being loaded via 411*68d75effSDimitry Andric // dlopen() and the platform supports it. 412*68d75effSDimitry Andric if (SANITIZER_SUPPORTS_INIT_FOR_DLOPEN && UNLIKELY(HandleDlopenInit())) { 413*68d75effSDimitry Andric asan_init_is_running = false; 414*68d75effSDimitry Andric VReport(1, "AddressSanitizer init is being performed for dlopen().\n"); 415*68d75effSDimitry Andric return; 416*68d75effSDimitry Andric } 417*68d75effSDimitry Andric 418*68d75effSDimitry Andric AsanCheckIncompatibleRT(); 419*68d75effSDimitry Andric AsanCheckDynamicRTPrereqs(); 420*68d75effSDimitry Andric AvoidCVE_2016_2143(); 421*68d75effSDimitry Andric 422*68d75effSDimitry Andric SetCanPoisonMemory(flags()->poison_heap); 423*68d75effSDimitry Andric SetMallocContextSize(common_flags()->malloc_context_size); 424*68d75effSDimitry Andric 425*68d75effSDimitry Andric InitializePlatformExceptionHandlers(); 426*68d75effSDimitry Andric 427*68d75effSDimitry Andric InitializeHighMemEnd(); 428*68d75effSDimitry Andric 429*68d75effSDimitry Andric // Make sure we are not statically linked. 430*68d75effSDimitry Andric AsanDoesNotSupportStaticLinkage(); 431*68d75effSDimitry Andric 432*68d75effSDimitry Andric // Install tool-specific callbacks in sanitizer_common. 433*68d75effSDimitry Andric AddDieCallback(AsanDie); 434*68d75effSDimitry Andric SetCheckFailedCallback(AsanCheckFailed); 435*68d75effSDimitry Andric SetPrintfAndReportCallback(AppendToErrorMessageBuffer); 436*68d75effSDimitry Andric 437*68d75effSDimitry Andric __sanitizer_set_report_path(common_flags()->log_path); 438*68d75effSDimitry Andric 439*68d75effSDimitry Andric __asan_option_detect_stack_use_after_return = 440*68d75effSDimitry Andric flags()->detect_stack_use_after_return; 441*68d75effSDimitry Andric 442*68d75effSDimitry Andric __sanitizer::InitializePlatformEarly(); 443*68d75effSDimitry Andric 444*68d75effSDimitry Andric // Re-exec ourselves if we need to set additional env or command line args. 445*68d75effSDimitry Andric MaybeReexec(); 446*68d75effSDimitry Andric 447*68d75effSDimitry Andric // Setup internal allocator callback. 448*68d75effSDimitry Andric SetLowLevelAllocateMinAlignment(SHADOW_GRANULARITY); 449*68d75effSDimitry Andric SetLowLevelAllocateCallback(OnLowLevelAllocate); 450*68d75effSDimitry Andric 451*68d75effSDimitry Andric InitializeAsanInterceptors(); 452*68d75effSDimitry Andric CheckASLR(); 453*68d75effSDimitry Andric 454*68d75effSDimitry Andric // Enable system log ("adb logcat") on Android. 455*68d75effSDimitry Andric // Doing this before interceptors are initialized crashes in: 456*68d75effSDimitry Andric // AsanInitInternal -> android_log_write -> __interceptor_strcmp 457*68d75effSDimitry Andric AndroidLogInit(); 458*68d75effSDimitry Andric 459*68d75effSDimitry Andric ReplaceSystemMalloc(); 460*68d75effSDimitry Andric 461*68d75effSDimitry Andric DisableCoreDumperIfNecessary(); 462*68d75effSDimitry Andric 463*68d75effSDimitry Andric InitializeShadowMemory(); 464*68d75effSDimitry Andric 465*68d75effSDimitry Andric AsanTSDInit(PlatformTSDDtor); 466*68d75effSDimitry Andric InstallDeadlySignalHandlers(AsanOnDeadlySignal); 467*68d75effSDimitry Andric 468*68d75effSDimitry Andric AllocatorOptions allocator_options; 469*68d75effSDimitry Andric allocator_options.SetFrom(flags(), common_flags()); 470*68d75effSDimitry Andric InitializeAllocator(allocator_options); 471*68d75effSDimitry Andric 472*68d75effSDimitry Andric #ifdef START_BACKGROUND_THREAD_IN_ASAN_INTERNAL 473*68d75effSDimitry Andric MaybeStartBackgroudThread(); 474*68d75effSDimitry Andric SetSoftRssLimitExceededCallback(AsanSoftRssLimitExceededCallback); 475*68d75effSDimitry Andric #endif 476*68d75effSDimitry Andric 477*68d75effSDimitry Andric // On Linux AsanThread::ThreadStart() calls malloc() that's why asan_inited 478*68d75effSDimitry Andric // should be set to 1 prior to initializing the threads. 479*68d75effSDimitry Andric asan_inited = 1; 480*68d75effSDimitry Andric asan_init_is_running = false; 481*68d75effSDimitry Andric 482*68d75effSDimitry Andric if (flags()->atexit) 483*68d75effSDimitry Andric Atexit(asan_atexit); 484*68d75effSDimitry Andric 485*68d75effSDimitry Andric InitializeCoverage(common_flags()->coverage, common_flags()->coverage_dir); 486*68d75effSDimitry Andric 487*68d75effSDimitry Andric // Now that ASan runtime is (mostly) initialized, deactivate it if 488*68d75effSDimitry Andric // necessary, so that it can be re-activated when requested. 489*68d75effSDimitry Andric if (flags()->start_deactivated) 490*68d75effSDimitry Andric AsanDeactivate(); 491*68d75effSDimitry Andric 492*68d75effSDimitry Andric // interceptors 493*68d75effSDimitry Andric InitTlsSize(); 494*68d75effSDimitry Andric 495*68d75effSDimitry Andric // Create main thread. 496*68d75effSDimitry Andric AsanThread *main_thread = CreateMainThread(); 497*68d75effSDimitry Andric CHECK_EQ(0, main_thread->tid()); 498*68d75effSDimitry Andric force_interface_symbols(); // no-op. 499*68d75effSDimitry Andric SanitizerInitializeUnwinder(); 500*68d75effSDimitry Andric 501*68d75effSDimitry Andric if (CAN_SANITIZE_LEAKS) { 502*68d75effSDimitry Andric __lsan::InitCommonLsan(); 503*68d75effSDimitry Andric if (common_flags()->detect_leaks && common_flags()->leak_check_at_exit) { 504*68d75effSDimitry Andric if (flags()->halt_on_error) 505*68d75effSDimitry Andric Atexit(__lsan::DoLeakCheck); 506*68d75effSDimitry Andric else 507*68d75effSDimitry Andric Atexit(__lsan::DoRecoverableLeakCheckVoid); 508*68d75effSDimitry Andric } 509*68d75effSDimitry Andric } 510*68d75effSDimitry Andric 511*68d75effSDimitry Andric #if CAN_SANITIZE_UB 512*68d75effSDimitry Andric __ubsan::InitAsPlugin(); 513*68d75effSDimitry Andric #endif 514*68d75effSDimitry Andric 515*68d75effSDimitry Andric InitializeSuppressions(); 516*68d75effSDimitry Andric 517*68d75effSDimitry Andric if (CAN_SANITIZE_LEAKS) { 518*68d75effSDimitry Andric // LateInitialize() calls dlsym, which can allocate an error string buffer 519*68d75effSDimitry Andric // in the TLS. Let's ignore the allocation to avoid reporting a leak. 520*68d75effSDimitry Andric __lsan::ScopedInterceptorDisabler disabler; 521*68d75effSDimitry Andric Symbolizer::LateInitialize(); 522*68d75effSDimitry Andric } else { 523*68d75effSDimitry Andric Symbolizer::LateInitialize(); 524*68d75effSDimitry Andric } 525*68d75effSDimitry Andric 526*68d75effSDimitry Andric VReport(1, "AddressSanitizer Init done\n"); 527*68d75effSDimitry Andric 528*68d75effSDimitry Andric if (flags()->sleep_after_init) { 529*68d75effSDimitry Andric Report("Sleeping for %d second(s)\n", flags()->sleep_after_init); 530*68d75effSDimitry Andric SleepForSeconds(flags()->sleep_after_init); 531*68d75effSDimitry Andric } 532*68d75effSDimitry Andric } 533*68d75effSDimitry Andric 534*68d75effSDimitry Andric // Initialize as requested from some part of ASan runtime library (interceptors, 535*68d75effSDimitry Andric // allocator, etc). 536*68d75effSDimitry Andric void AsanInitFromRtl() { 537*68d75effSDimitry Andric AsanInitInternal(); 538*68d75effSDimitry Andric } 539*68d75effSDimitry Andric 540*68d75effSDimitry Andric #if ASAN_DYNAMIC 541*68d75effSDimitry Andric // Initialize runtime in case it's LD_PRELOAD-ed into unsanitized executable 542*68d75effSDimitry Andric // (and thus normal initializers from .preinit_array or modules haven't run). 543*68d75effSDimitry Andric 544*68d75effSDimitry Andric class AsanInitializer { 545*68d75effSDimitry Andric public: 546*68d75effSDimitry Andric AsanInitializer() { 547*68d75effSDimitry Andric AsanInitFromRtl(); 548*68d75effSDimitry Andric } 549*68d75effSDimitry Andric }; 550*68d75effSDimitry Andric 551*68d75effSDimitry Andric static AsanInitializer asan_initializer; 552*68d75effSDimitry Andric #endif // ASAN_DYNAMIC 553*68d75effSDimitry Andric 554*68d75effSDimitry Andric } // namespace __asan 555*68d75effSDimitry Andric 556*68d75effSDimitry Andric // ---------------------- Interface ---------------- {{{1 557*68d75effSDimitry Andric using namespace __asan; 558*68d75effSDimitry Andric 559*68d75effSDimitry Andric void NOINLINE __asan_handle_no_return() { 560*68d75effSDimitry Andric if (asan_init_is_running) 561*68d75effSDimitry Andric return; 562*68d75effSDimitry Andric 563*68d75effSDimitry Andric int local_stack; 564*68d75effSDimitry Andric AsanThread *curr_thread = GetCurrentThread(); 565*68d75effSDimitry Andric uptr PageSize = GetPageSizeCached(); 566*68d75effSDimitry Andric uptr top, bottom; 567*68d75effSDimitry Andric if (curr_thread) { 568*68d75effSDimitry Andric top = curr_thread->stack_top(); 569*68d75effSDimitry Andric bottom = ((uptr)&local_stack - PageSize) & ~(PageSize - 1); 570*68d75effSDimitry Andric } else if (SANITIZER_RTEMS) { 571*68d75effSDimitry Andric // Give up On RTEMS. 572*68d75effSDimitry Andric return; 573*68d75effSDimitry Andric } else { 574*68d75effSDimitry Andric CHECK(!SANITIZER_FUCHSIA); 575*68d75effSDimitry Andric // If we haven't seen this thread, try asking the OS for stack bounds. 576*68d75effSDimitry Andric uptr tls_addr, tls_size, stack_size; 577*68d75effSDimitry Andric GetThreadStackAndTls(/*main=*/false, &bottom, &stack_size, &tls_addr, 578*68d75effSDimitry Andric &tls_size); 579*68d75effSDimitry Andric top = bottom + stack_size; 580*68d75effSDimitry Andric } 581*68d75effSDimitry Andric static const uptr kMaxExpectedCleanupSize = 64 << 20; // 64M 582*68d75effSDimitry Andric if (top - bottom > kMaxExpectedCleanupSize) { 583*68d75effSDimitry Andric static bool reported_warning = false; 584*68d75effSDimitry Andric if (reported_warning) 585*68d75effSDimitry Andric return; 586*68d75effSDimitry Andric reported_warning = true; 587*68d75effSDimitry Andric Report("WARNING: ASan is ignoring requested __asan_handle_no_return: " 588*68d75effSDimitry Andric "stack top: %p; bottom %p; size: %p (%zd)\n" 589*68d75effSDimitry Andric "False positive error reports may follow\n" 590*68d75effSDimitry Andric "For details see " 591*68d75effSDimitry Andric "https://github.com/google/sanitizers/issues/189\n", 592*68d75effSDimitry Andric top, bottom, top - bottom, top - bottom); 593*68d75effSDimitry Andric return; 594*68d75effSDimitry Andric } 595*68d75effSDimitry Andric PoisonShadow(bottom, top - bottom, 0); 596*68d75effSDimitry Andric if (curr_thread && curr_thread->has_fake_stack()) 597*68d75effSDimitry Andric curr_thread->fake_stack()->HandleNoReturn(); 598*68d75effSDimitry Andric } 599*68d75effSDimitry Andric 600*68d75effSDimitry Andric extern "C" void *__asan_extra_spill_area() { 601*68d75effSDimitry Andric AsanThread *t = GetCurrentThread(); 602*68d75effSDimitry Andric CHECK(t); 603*68d75effSDimitry Andric return t->extra_spill_area(); 604*68d75effSDimitry Andric } 605*68d75effSDimitry Andric 606*68d75effSDimitry Andric void __asan_handle_vfork(void *sp) { 607*68d75effSDimitry Andric AsanThread *t = GetCurrentThread(); 608*68d75effSDimitry Andric CHECK(t); 609*68d75effSDimitry Andric uptr bottom = t->stack_bottom(); 610*68d75effSDimitry Andric PoisonShadow(bottom, (uptr)sp - bottom, 0); 611*68d75effSDimitry Andric } 612*68d75effSDimitry Andric 613*68d75effSDimitry Andric void NOINLINE __asan_set_death_callback(void (*callback)(void)) { 614*68d75effSDimitry Andric SetUserDieCallback(callback); 615*68d75effSDimitry Andric } 616*68d75effSDimitry Andric 617*68d75effSDimitry Andric // Initialize as requested from instrumented application code. 618*68d75effSDimitry Andric // We use this call as a trigger to wake up ASan from deactivated state. 619*68d75effSDimitry Andric void __asan_init() { 620*68d75effSDimitry Andric AsanActivate(); 621*68d75effSDimitry Andric AsanInitInternal(); 622*68d75effSDimitry Andric } 623*68d75effSDimitry Andric 624*68d75effSDimitry Andric void __asan_version_mismatch_check() { 625*68d75effSDimitry Andric // Do nothing. 626*68d75effSDimitry Andric } 627