10b57cec5SDimitry Andric //===-- hwasan.cpp --------------------------------------------------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // This file is a part of HWAddressSanitizer. 100b57cec5SDimitry Andric // 110b57cec5SDimitry Andric // HWAddressSanitizer runtime. 120b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 130b57cec5SDimitry Andric 140b57cec5SDimitry Andric #include "hwasan.h" 155ffd83dbSDimitry Andric 160b57cec5SDimitry Andric #include "hwasan_checks.h" 170b57cec5SDimitry Andric #include "hwasan_dynamic_shadow.h" 185ffd83dbSDimitry Andric #include "hwasan_globals.h" 190b57cec5SDimitry Andric #include "hwasan_poisoning.h" 200b57cec5SDimitry Andric #include "hwasan_report.h" 210b57cec5SDimitry Andric #include "hwasan_thread.h" 220b57cec5SDimitry Andric #include "hwasan_thread_list.h" 230b57cec5SDimitry Andric #include "sanitizer_common/sanitizer_atomic.h" 240b57cec5SDimitry Andric #include "sanitizer_common/sanitizer_common.h" 250b57cec5SDimitry Andric #include "sanitizer_common/sanitizer_flag_parser.h" 260b57cec5SDimitry Andric #include "sanitizer_common/sanitizer_flags.h" 270b57cec5SDimitry Andric #include "sanitizer_common/sanitizer_libc.h" 280b57cec5SDimitry Andric #include "sanitizer_common/sanitizer_procmaps.h" 290b57cec5SDimitry Andric #include "sanitizer_common/sanitizer_stackdepot.h" 300b57cec5SDimitry Andric #include "sanitizer_common/sanitizer_stacktrace.h" 310b57cec5SDimitry Andric #include "sanitizer_common/sanitizer_symbolizer.h" 320b57cec5SDimitry Andric #include "ubsan/ubsan_flags.h" 330b57cec5SDimitry Andric #include "ubsan/ubsan_init.h" 340b57cec5SDimitry Andric 350b57cec5SDimitry Andric // ACHTUNG! No system header includes in this file. 360b57cec5SDimitry Andric 370b57cec5SDimitry Andric using namespace __sanitizer; 380b57cec5SDimitry Andric 390b57cec5SDimitry Andric namespace __hwasan { 400b57cec5SDimitry Andric 410b57cec5SDimitry Andric static Flags hwasan_flags; 420b57cec5SDimitry Andric 430b57cec5SDimitry Andric Flags *flags() { 440b57cec5SDimitry Andric return &hwasan_flags; 450b57cec5SDimitry Andric } 460b57cec5SDimitry Andric 470b57cec5SDimitry Andric int hwasan_inited = 0; 480b57cec5SDimitry Andric int hwasan_instrumentation_inited = 0; 490b57cec5SDimitry Andric bool hwasan_init_is_running; 500b57cec5SDimitry Andric 510b57cec5SDimitry Andric int hwasan_report_count = 0; 520b57cec5SDimitry Andric 53*fe6060f1SDimitry Andric uptr kLowShadowStart; 54*fe6060f1SDimitry Andric uptr kLowShadowEnd; 55*fe6060f1SDimitry Andric uptr kHighShadowStart; 56*fe6060f1SDimitry Andric uptr kHighShadowEnd; 57*fe6060f1SDimitry Andric 580b57cec5SDimitry Andric void Flags::SetDefaults() { 590b57cec5SDimitry Andric #define HWASAN_FLAG(Type, Name, DefaultValue, Description) Name = DefaultValue; 600b57cec5SDimitry Andric #include "hwasan_flags.inc" 610b57cec5SDimitry Andric #undef HWASAN_FLAG 620b57cec5SDimitry Andric } 630b57cec5SDimitry Andric 640b57cec5SDimitry Andric static void RegisterHwasanFlags(FlagParser *parser, Flags *f) { 650b57cec5SDimitry Andric #define HWASAN_FLAG(Type, Name, DefaultValue, Description) \ 660b57cec5SDimitry Andric RegisterFlag(parser, #Name, Description, &f->Name); 670b57cec5SDimitry Andric #include "hwasan_flags.inc" 680b57cec5SDimitry Andric #undef HWASAN_FLAG 690b57cec5SDimitry Andric } 700b57cec5SDimitry Andric 710b57cec5SDimitry Andric static void InitializeFlags() { 720b57cec5SDimitry Andric SetCommonFlagsDefaults(); 730b57cec5SDimitry Andric { 740b57cec5SDimitry Andric CommonFlags cf; 750b57cec5SDimitry Andric cf.CopyFrom(*common_flags()); 760b57cec5SDimitry Andric cf.external_symbolizer_path = GetEnv("HWASAN_SYMBOLIZER_PATH"); 770b57cec5SDimitry Andric cf.malloc_context_size = 20; 780b57cec5SDimitry Andric cf.handle_ioctl = true; 790b57cec5SDimitry Andric // FIXME: test and enable. 800b57cec5SDimitry Andric cf.check_printf = false; 810b57cec5SDimitry Andric cf.intercept_tls_get_addr = true; 820b57cec5SDimitry Andric cf.exitcode = 99; 830b57cec5SDimitry Andric // 8 shadow pages ~512kB, small enough to cover common stack sizes. 840b57cec5SDimitry Andric cf.clear_shadow_mmap_threshold = 4096 * (SANITIZER_ANDROID ? 2 : 8); 850b57cec5SDimitry Andric // Sigtrap is used in error reporting. 860b57cec5SDimitry Andric cf.handle_sigtrap = kHandleSignalExclusive; 870b57cec5SDimitry Andric 880b57cec5SDimitry Andric #if SANITIZER_ANDROID 890b57cec5SDimitry Andric // Let platform handle other signals. It is better at reporting them then we 900b57cec5SDimitry Andric // are. 910b57cec5SDimitry Andric cf.handle_segv = kHandleSignalNo; 920b57cec5SDimitry Andric cf.handle_sigbus = kHandleSignalNo; 930b57cec5SDimitry Andric cf.handle_abort = kHandleSignalNo; 940b57cec5SDimitry Andric cf.handle_sigill = kHandleSignalNo; 950b57cec5SDimitry Andric cf.handle_sigfpe = kHandleSignalNo; 960b57cec5SDimitry Andric #endif 970b57cec5SDimitry Andric OverrideCommonFlags(cf); 980b57cec5SDimitry Andric } 990b57cec5SDimitry Andric 1000b57cec5SDimitry Andric Flags *f = flags(); 1010b57cec5SDimitry Andric f->SetDefaults(); 1020b57cec5SDimitry Andric 1030b57cec5SDimitry Andric FlagParser parser; 1040b57cec5SDimitry Andric RegisterHwasanFlags(&parser, f); 1050b57cec5SDimitry Andric RegisterCommonFlags(&parser); 1060b57cec5SDimitry Andric 1070b57cec5SDimitry Andric #if HWASAN_CONTAINS_UBSAN 1080b57cec5SDimitry Andric __ubsan::Flags *uf = __ubsan::flags(); 1090b57cec5SDimitry Andric uf->SetDefaults(); 1100b57cec5SDimitry Andric 1110b57cec5SDimitry Andric FlagParser ubsan_parser; 1120b57cec5SDimitry Andric __ubsan::RegisterUbsanFlags(&ubsan_parser, uf); 1130b57cec5SDimitry Andric RegisterCommonFlags(&ubsan_parser); 1140b57cec5SDimitry Andric #endif 1150b57cec5SDimitry Andric 1160b57cec5SDimitry Andric // Override from user-specified string. 1170b57cec5SDimitry Andric if (__hwasan_default_options) 1180b57cec5SDimitry Andric parser.ParseString(__hwasan_default_options()); 1190b57cec5SDimitry Andric #if HWASAN_CONTAINS_UBSAN 120e8d8bef9SDimitry Andric const char *ubsan_default_options = __ubsan_default_options(); 1210b57cec5SDimitry Andric ubsan_parser.ParseString(ubsan_default_options); 1220b57cec5SDimitry Andric #endif 1230b57cec5SDimitry Andric 1240b57cec5SDimitry Andric parser.ParseStringFromEnv("HWASAN_OPTIONS"); 1250b57cec5SDimitry Andric #if HWASAN_CONTAINS_UBSAN 1260b57cec5SDimitry Andric ubsan_parser.ParseStringFromEnv("UBSAN_OPTIONS"); 1270b57cec5SDimitry Andric #endif 1280b57cec5SDimitry Andric 1290b57cec5SDimitry Andric InitializeCommonFlags(); 1300b57cec5SDimitry Andric 1310b57cec5SDimitry Andric if (Verbosity()) ReportUnrecognizedFlags(); 1320b57cec5SDimitry Andric 1330b57cec5SDimitry Andric if (common_flags()->help) parser.PrintFlagDescriptions(); 1340b57cec5SDimitry Andric } 1350b57cec5SDimitry Andric 136*fe6060f1SDimitry Andric static void CheckUnwind() { 137*fe6060f1SDimitry Andric GET_FATAL_STACK_TRACE_PC_BP(StackTrace::GetCurrentPc(), GET_CURRENT_FRAME()); 138*fe6060f1SDimitry Andric stack.Print(); 1390b57cec5SDimitry Andric } 1400b57cec5SDimitry Andric 1410b57cec5SDimitry Andric static void HwasanFormatMemoryUsage(InternalScopedString &s) { 1420b57cec5SDimitry Andric HwasanThreadList &thread_list = hwasanThreadList(); 1430b57cec5SDimitry Andric auto thread_stats = thread_list.GetThreadStats(); 1440b57cec5SDimitry Andric auto *sds = StackDepotGetStats(); 1450b57cec5SDimitry Andric AllocatorStatCounters asc; 1460b57cec5SDimitry Andric GetAllocatorStats(asc); 1470b57cec5SDimitry Andric s.append( 1480b57cec5SDimitry Andric "HWASAN pid: %d rss: %zd threads: %zd stacks: %zd" 1490b57cec5SDimitry Andric " thr_aux: %zd stack_depot: %zd uniq_stacks: %zd" 1500b57cec5SDimitry Andric " heap: %zd", 1510b57cec5SDimitry Andric internal_getpid(), GetRSS(), thread_stats.n_live_threads, 1520b57cec5SDimitry Andric thread_stats.total_stack_size, 1530b57cec5SDimitry Andric thread_stats.n_live_threads * thread_list.MemoryUsedPerThread(), 1540b57cec5SDimitry Andric sds->allocated, sds->n_uniq_ids, asc[AllocatorStatMapped]); 1550b57cec5SDimitry Andric } 1560b57cec5SDimitry Andric 1570b57cec5SDimitry Andric #if SANITIZER_ANDROID 158*fe6060f1SDimitry Andric static constexpr uptr kMemoryUsageBufferSize = 4096; 159*fe6060f1SDimitry Andric 1600b57cec5SDimitry Andric static char *memory_usage_buffer = nullptr; 1610b57cec5SDimitry Andric 1620b57cec5SDimitry Andric static void InitMemoryUsage() { 1630b57cec5SDimitry Andric memory_usage_buffer = 1640b57cec5SDimitry Andric (char *)MmapOrDie(kMemoryUsageBufferSize, "memory usage string"); 1650b57cec5SDimitry Andric CHECK(memory_usage_buffer); 1660b57cec5SDimitry Andric memory_usage_buffer[0] = '\0'; 1670b57cec5SDimitry Andric DecorateMapping((uptr)memory_usage_buffer, kMemoryUsageBufferSize, 1680b57cec5SDimitry Andric memory_usage_buffer); 1690b57cec5SDimitry Andric } 1700b57cec5SDimitry Andric 1710b57cec5SDimitry Andric void UpdateMemoryUsage() { 1720b57cec5SDimitry Andric if (!flags()->export_memory_stats) 1730b57cec5SDimitry Andric return; 1740b57cec5SDimitry Andric if (!memory_usage_buffer) 1750b57cec5SDimitry Andric InitMemoryUsage(); 176*fe6060f1SDimitry Andric InternalScopedString s; 1770b57cec5SDimitry Andric HwasanFormatMemoryUsage(s); 1780b57cec5SDimitry Andric internal_strncpy(memory_usage_buffer, s.data(), kMemoryUsageBufferSize - 1); 1790b57cec5SDimitry Andric memory_usage_buffer[kMemoryUsageBufferSize - 1] = '\0'; 1800b57cec5SDimitry Andric } 1810b57cec5SDimitry Andric #else 1820b57cec5SDimitry Andric void UpdateMemoryUsage() {} 1830b57cec5SDimitry Andric #endif 1840b57cec5SDimitry Andric 185*fe6060f1SDimitry Andric void HwasanAtExit() { 186*fe6060f1SDimitry Andric if (common_flags()->print_module_map) 187*fe6060f1SDimitry Andric DumpProcessMap(); 188*fe6060f1SDimitry Andric if (flags()->print_stats && (flags()->atexit || hwasan_report_count > 0)) 189*fe6060f1SDimitry Andric ReportStats(); 190*fe6060f1SDimitry Andric if (hwasan_report_count > 0) { 191*fe6060f1SDimitry Andric // ReportAtExitStatistics(); 192*fe6060f1SDimitry Andric if (common_flags()->exitcode) 193*fe6060f1SDimitry Andric internal__exit(common_flags()->exitcode); 194*fe6060f1SDimitry Andric } 195*fe6060f1SDimitry Andric } 196*fe6060f1SDimitry Andric 197*fe6060f1SDimitry Andric void HandleTagMismatch(AccessInfo ai, uptr pc, uptr frame, void *uc, 198*fe6060f1SDimitry Andric uptr *registers_frame) { 199*fe6060f1SDimitry Andric InternalMmapVector<BufferedStackTrace> stack_buffer(1); 200*fe6060f1SDimitry Andric BufferedStackTrace *stack = stack_buffer.data(); 201*fe6060f1SDimitry Andric stack->Reset(); 202*fe6060f1SDimitry Andric stack->Unwind(pc, frame, uc, common_flags()->fast_unwind_on_fatal); 203*fe6060f1SDimitry Andric 204*fe6060f1SDimitry Andric // The second stack frame contains the failure __hwasan_check function, as 205*fe6060f1SDimitry Andric // we have a stack frame for the registers saved in __hwasan_tag_mismatch that 206*fe6060f1SDimitry Andric // we wish to ignore. This (currently) only occurs on AArch64, as x64 207*fe6060f1SDimitry Andric // implementations use SIGTRAP to implement the failure, and thus do not go 208*fe6060f1SDimitry Andric // through the stack saver. 209*fe6060f1SDimitry Andric if (registers_frame && stack->trace && stack->size > 0) { 210*fe6060f1SDimitry Andric stack->trace++; 211*fe6060f1SDimitry Andric stack->size--; 212*fe6060f1SDimitry Andric } 213*fe6060f1SDimitry Andric 214*fe6060f1SDimitry Andric bool fatal = flags()->halt_on_error || !ai.recover; 215*fe6060f1SDimitry Andric ReportTagMismatch(stack, ai.addr, ai.size, ai.is_store, fatal, 216*fe6060f1SDimitry Andric registers_frame); 217*fe6060f1SDimitry Andric } 218*fe6060f1SDimitry Andric 219*fe6060f1SDimitry Andric void HwasanTagMismatch(uptr addr, uptr access_info, uptr *registers_frame, 220*fe6060f1SDimitry Andric size_t outsize) { 221*fe6060f1SDimitry Andric __hwasan::AccessInfo ai; 222*fe6060f1SDimitry Andric ai.is_store = access_info & 0x10; 223*fe6060f1SDimitry Andric ai.is_load = !ai.is_store; 224*fe6060f1SDimitry Andric ai.recover = access_info & 0x20; 225*fe6060f1SDimitry Andric ai.addr = addr; 226*fe6060f1SDimitry Andric if ((access_info & 0xf) == 0xf) 227*fe6060f1SDimitry Andric ai.size = outsize; 228*fe6060f1SDimitry Andric else 229*fe6060f1SDimitry Andric ai.size = 1 << (access_info & 0xf); 230*fe6060f1SDimitry Andric 231*fe6060f1SDimitry Andric HandleTagMismatch(ai, (uptr)__builtin_return_address(0), 232*fe6060f1SDimitry Andric (uptr)__builtin_frame_address(0), nullptr, registers_frame); 233*fe6060f1SDimitry Andric __builtin_unreachable(); 234*fe6060f1SDimitry Andric } 235*fe6060f1SDimitry Andric 236*fe6060f1SDimitry Andric Thread *GetCurrentThread() { 237*fe6060f1SDimitry Andric uptr *ThreadLongPtr = GetCurrentThreadLongPtr(); 238*fe6060f1SDimitry Andric if (UNLIKELY(*ThreadLongPtr == 0)) 239*fe6060f1SDimitry Andric return nullptr; 240*fe6060f1SDimitry Andric auto *R = (StackAllocationsRingBuffer *)ThreadLongPtr; 241*fe6060f1SDimitry Andric return hwasanThreadList().GetThreadByBufferAddress((uptr)R->Next()); 242*fe6060f1SDimitry Andric } 243*fe6060f1SDimitry Andric 2440b57cec5SDimitry Andric } // namespace __hwasan 2450b57cec5SDimitry Andric 24668d75effSDimitry Andric using namespace __hwasan; 24768d75effSDimitry Andric 2480b57cec5SDimitry Andric void __sanitizer::BufferedStackTrace::UnwindImpl( 2490b57cec5SDimitry Andric uptr pc, uptr bp, void *context, bool request_fast, u32 max_depth) { 2500b57cec5SDimitry Andric Thread *t = GetCurrentThread(); 2510b57cec5SDimitry Andric if (!t) { 2525ffd83dbSDimitry Andric // The thread is still being created, or has already been destroyed. 2530b57cec5SDimitry Andric size = 0; 2540b57cec5SDimitry Andric return; 2550b57cec5SDimitry Andric } 2565ffd83dbSDimitry Andric Unwind(max_depth, pc, bp, context, t->stack_top(), t->stack_bottom(), 2575ffd83dbSDimitry Andric request_fast); 2580b57cec5SDimitry Andric } 2590b57cec5SDimitry Andric 2605ffd83dbSDimitry Andric static bool InitializeSingleGlobal(const hwasan_global &global) { 2615ffd83dbSDimitry Andric uptr full_granule_size = RoundDownTo(global.size(), 16); 2625ffd83dbSDimitry Andric TagMemoryAligned(global.addr(), full_granule_size, global.tag()); 2635ffd83dbSDimitry Andric if (global.size() % 16) 2645ffd83dbSDimitry Andric TagMemoryAligned(global.addr() + full_granule_size, 16, global.size() % 16); 2655ffd83dbSDimitry Andric return false; 26668d75effSDimitry Andric } 26768d75effSDimitry Andric 26868d75effSDimitry Andric static void InitLoadedGlobals() { 26968d75effSDimitry Andric dl_iterate_phdr( 2705ffd83dbSDimitry Andric [](dl_phdr_info *info, size_t /* size */, void * /* data */) -> int { 2715ffd83dbSDimitry Andric for (const hwasan_global &global : HwasanGlobalsFor( 2725ffd83dbSDimitry Andric info->dlpi_addr, info->dlpi_phdr, info->dlpi_phnum)) 2735ffd83dbSDimitry Andric InitializeSingleGlobal(global); 27468d75effSDimitry Andric return 0; 27568d75effSDimitry Andric }, 27668d75effSDimitry Andric nullptr); 27768d75effSDimitry Andric } 27868d75effSDimitry Andric 27968d75effSDimitry Andric // Prepare to run instrumented code on the main thread. 28068d75effSDimitry Andric static void InitInstrumentation() { 28168d75effSDimitry Andric if (hwasan_instrumentation_inited) return; 28268d75effSDimitry Andric 283*fe6060f1SDimitry Andric InitializeOsSupport(); 28468d75effSDimitry Andric 28568d75effSDimitry Andric if (!InitShadow()) { 28668d75effSDimitry Andric Printf("FATAL: HWAddressSanitizer cannot mmap the shadow memory.\n"); 28768d75effSDimitry Andric DumpProcessMap(); 28868d75effSDimitry Andric Die(); 28968d75effSDimitry Andric } 29068d75effSDimitry Andric 29168d75effSDimitry Andric InitThreads(); 29268d75effSDimitry Andric 29368d75effSDimitry Andric hwasan_instrumentation_inited = 1; 29468d75effSDimitry Andric } 29568d75effSDimitry Andric 29668d75effSDimitry Andric // Interface. 2970b57cec5SDimitry Andric 2980b57cec5SDimitry Andric uptr __hwasan_shadow_memory_dynamic_address; // Global interface symbol. 2990b57cec5SDimitry Andric 3000b57cec5SDimitry Andric // This function was used by the old frame descriptor mechanism. We keep it 3010b57cec5SDimitry Andric // around to avoid breaking ABI. 3020b57cec5SDimitry Andric void __hwasan_init_frames(uptr beg, uptr end) {} 3030b57cec5SDimitry Andric 3040b57cec5SDimitry Andric void __hwasan_init_static() { 3050b57cec5SDimitry Andric InitShadowGOT(); 3060b57cec5SDimitry Andric InitInstrumentation(); 30768d75effSDimitry Andric 30868d75effSDimitry Andric // In the non-static code path we call dl_iterate_phdr here. But at this point 30968d75effSDimitry Andric // libc might not have been initialized enough for dl_iterate_phdr to work. 31068d75effSDimitry Andric // Fortunately, since this is a statically linked executable we can use the 31168d75effSDimitry Andric // linker-defined symbol __ehdr_start to find the only relevant set of phdrs. 31268d75effSDimitry Andric extern ElfW(Ehdr) __ehdr_start; 3135ffd83dbSDimitry Andric for (const hwasan_global &global : HwasanGlobalsFor( 3145ffd83dbSDimitry Andric /* base */ 0, 31568d75effSDimitry Andric reinterpret_cast<const ElfW(Phdr) *>( 3165ffd83dbSDimitry Andric reinterpret_cast<const char *>(&__ehdr_start) + 3175ffd83dbSDimitry Andric __ehdr_start.e_phoff), 3185ffd83dbSDimitry Andric __ehdr_start.e_phnum)) 3195ffd83dbSDimitry Andric InitializeSingleGlobal(global); 3200b57cec5SDimitry Andric } 3210b57cec5SDimitry Andric 3220b57cec5SDimitry Andric void __hwasan_init() { 3230b57cec5SDimitry Andric CHECK(!hwasan_init_is_running); 3240b57cec5SDimitry Andric if (hwasan_inited) return; 3250b57cec5SDimitry Andric hwasan_init_is_running = 1; 3260b57cec5SDimitry Andric SanitizerToolName = "HWAddressSanitizer"; 3270b57cec5SDimitry Andric 3280b57cec5SDimitry Andric InitTlsSize(); 3290b57cec5SDimitry Andric 3300b57cec5SDimitry Andric CacheBinaryName(); 3310b57cec5SDimitry Andric InitializeFlags(); 3320b57cec5SDimitry Andric 3330b57cec5SDimitry Andric // Install tool-specific callbacks in sanitizer_common. 334*fe6060f1SDimitry Andric SetCheckUnwindCallback(CheckUnwind); 3350b57cec5SDimitry Andric 3360b57cec5SDimitry Andric __sanitizer_set_report_path(common_flags()->log_path); 3370b57cec5SDimitry Andric 3380b57cec5SDimitry Andric AndroidTestTlsSlot(); 3390b57cec5SDimitry Andric 3400b57cec5SDimitry Andric DisableCoreDumperIfNecessary(); 3410b57cec5SDimitry Andric 3420b57cec5SDimitry Andric InitInstrumentation(); 34368d75effSDimitry Andric InitLoadedGlobals(); 3440b57cec5SDimitry Andric 3450b57cec5SDimitry Andric // Needs to be called here because flags()->random_tags might not have been 3460b57cec5SDimitry Andric // initialized when InitInstrumentation() was called. 3470b57cec5SDimitry Andric GetCurrentThread()->InitRandomState(); 3480b57cec5SDimitry Andric 3490b57cec5SDimitry Andric SetPrintfAndReportCallback(AppendToErrorMessageBuffer); 3500b57cec5SDimitry Andric // This may call libc -> needs initialized shadow. 3510b57cec5SDimitry Andric AndroidLogInit(); 3520b57cec5SDimitry Andric 3530b57cec5SDimitry Andric InitializeInterceptors(); 3540b57cec5SDimitry Andric InstallDeadlySignalHandlers(HwasanOnDeadlySignal); 3550b57cec5SDimitry Andric InstallAtExitHandler(); // Needs __cxa_atexit interceptor. 3560b57cec5SDimitry Andric 3570b57cec5SDimitry Andric InitializeCoverage(common_flags()->coverage, common_flags()->coverage_dir); 3580b57cec5SDimitry Andric 3590b57cec5SDimitry Andric HwasanTSDInit(); 3600b57cec5SDimitry Andric HwasanTSDThreadInit(); 3610b57cec5SDimitry Andric 3620b57cec5SDimitry Andric HwasanAllocatorInit(); 3630b57cec5SDimitry Andric 3640b57cec5SDimitry Andric #if HWASAN_CONTAINS_UBSAN 3650b57cec5SDimitry Andric __ubsan::InitAsPlugin(); 3660b57cec5SDimitry Andric #endif 3670b57cec5SDimitry Andric 3680b57cec5SDimitry Andric VPrintf(1, "HWAddressSanitizer init done\n"); 3690b57cec5SDimitry Andric 3700b57cec5SDimitry Andric hwasan_init_is_running = 0; 3710b57cec5SDimitry Andric hwasan_inited = 1; 3720b57cec5SDimitry Andric } 3730b57cec5SDimitry Andric 37468d75effSDimitry Andric void __hwasan_library_loaded(ElfW(Addr) base, const ElfW(Phdr) * phdr, 37568d75effSDimitry Andric ElfW(Half) phnum) { 3765ffd83dbSDimitry Andric for (const hwasan_global &global : HwasanGlobalsFor(base, phdr, phnum)) 3775ffd83dbSDimitry Andric InitializeSingleGlobal(global); 37868d75effSDimitry Andric } 37968d75effSDimitry Andric 38068d75effSDimitry Andric void __hwasan_library_unloaded(ElfW(Addr) base, const ElfW(Phdr) * phdr, 38168d75effSDimitry Andric ElfW(Half) phnum) { 38268d75effSDimitry Andric for (; phnum != 0; ++phdr, --phnum) 38368d75effSDimitry Andric if (phdr->p_type == PT_LOAD) 38468d75effSDimitry Andric TagMemory(base + phdr->p_vaddr, phdr->p_memsz, 0); 38568d75effSDimitry Andric } 38668d75effSDimitry Andric 3870b57cec5SDimitry Andric void __hwasan_print_shadow(const void *p, uptr sz) { 3880b57cec5SDimitry Andric uptr ptr_raw = UntagAddr(reinterpret_cast<uptr>(p)); 3890b57cec5SDimitry Andric uptr shadow_first = MemToShadow(ptr_raw); 3900b57cec5SDimitry Andric uptr shadow_last = MemToShadow(ptr_raw + sz - 1); 3910b57cec5SDimitry Andric Printf("HWASan shadow map for %zx .. %zx (pointer tag %x)\n", ptr_raw, 3920b57cec5SDimitry Andric ptr_raw + sz, GetTagFromPointer((uptr)p)); 3930b57cec5SDimitry Andric for (uptr s = shadow_first; s <= shadow_last; ++s) 3940b57cec5SDimitry Andric Printf(" %zx: %x\n", ShadowToMem(s), *(tag_t *)s); 3950b57cec5SDimitry Andric } 3960b57cec5SDimitry Andric 3970b57cec5SDimitry Andric sptr __hwasan_test_shadow(const void *p, uptr sz) { 3980b57cec5SDimitry Andric if (sz == 0) 3990b57cec5SDimitry Andric return -1; 4000b57cec5SDimitry Andric tag_t ptr_tag = GetTagFromPointer((uptr)p); 4010b57cec5SDimitry Andric uptr ptr_raw = UntagAddr(reinterpret_cast<uptr>(p)); 4020b57cec5SDimitry Andric uptr shadow_first = MemToShadow(ptr_raw); 4030b57cec5SDimitry Andric uptr shadow_last = MemToShadow(ptr_raw + sz - 1); 4040b57cec5SDimitry Andric for (uptr s = shadow_first; s <= shadow_last; ++s) 4050b57cec5SDimitry Andric if (*(tag_t *)s != ptr_tag) { 4060b57cec5SDimitry Andric sptr offset = ShadowToMem(s) - ptr_raw; 4070b57cec5SDimitry Andric return offset < 0 ? 0 : offset; 4080b57cec5SDimitry Andric } 4090b57cec5SDimitry Andric return -1; 4100b57cec5SDimitry Andric } 4110b57cec5SDimitry Andric 4120b57cec5SDimitry Andric u16 __sanitizer_unaligned_load16(const uu16 *p) { 4130b57cec5SDimitry Andric return *p; 4140b57cec5SDimitry Andric } 4150b57cec5SDimitry Andric u32 __sanitizer_unaligned_load32(const uu32 *p) { 4160b57cec5SDimitry Andric return *p; 4170b57cec5SDimitry Andric } 4180b57cec5SDimitry Andric u64 __sanitizer_unaligned_load64(const uu64 *p) { 4190b57cec5SDimitry Andric return *p; 4200b57cec5SDimitry Andric } 4210b57cec5SDimitry Andric void __sanitizer_unaligned_store16(uu16 *p, u16 x) { 4220b57cec5SDimitry Andric *p = x; 4230b57cec5SDimitry Andric } 4240b57cec5SDimitry Andric void __sanitizer_unaligned_store32(uu32 *p, u32 x) { 4250b57cec5SDimitry Andric *p = x; 4260b57cec5SDimitry Andric } 4270b57cec5SDimitry Andric void __sanitizer_unaligned_store64(uu64 *p, u64 x) { 4280b57cec5SDimitry Andric *p = x; 4290b57cec5SDimitry Andric } 4300b57cec5SDimitry Andric 4310b57cec5SDimitry Andric void __hwasan_loadN(uptr p, uptr sz) { 4320b57cec5SDimitry Andric CheckAddressSized<ErrorAction::Abort, AccessType::Load>(p, sz); 4330b57cec5SDimitry Andric } 4340b57cec5SDimitry Andric void __hwasan_load1(uptr p) { 4350b57cec5SDimitry Andric CheckAddress<ErrorAction::Abort, AccessType::Load, 0>(p); 4360b57cec5SDimitry Andric } 4370b57cec5SDimitry Andric void __hwasan_load2(uptr p) { 4380b57cec5SDimitry Andric CheckAddress<ErrorAction::Abort, AccessType::Load, 1>(p); 4390b57cec5SDimitry Andric } 4400b57cec5SDimitry Andric void __hwasan_load4(uptr p) { 4410b57cec5SDimitry Andric CheckAddress<ErrorAction::Abort, AccessType::Load, 2>(p); 4420b57cec5SDimitry Andric } 4430b57cec5SDimitry Andric void __hwasan_load8(uptr p) { 4440b57cec5SDimitry Andric CheckAddress<ErrorAction::Abort, AccessType::Load, 3>(p); 4450b57cec5SDimitry Andric } 4460b57cec5SDimitry Andric void __hwasan_load16(uptr p) { 4470b57cec5SDimitry Andric CheckAddress<ErrorAction::Abort, AccessType::Load, 4>(p); 4480b57cec5SDimitry Andric } 4490b57cec5SDimitry Andric 4500b57cec5SDimitry Andric void __hwasan_loadN_noabort(uptr p, uptr sz) { 4510b57cec5SDimitry Andric CheckAddressSized<ErrorAction::Recover, AccessType::Load>(p, sz); 4520b57cec5SDimitry Andric } 4530b57cec5SDimitry Andric void __hwasan_load1_noabort(uptr p) { 4540b57cec5SDimitry Andric CheckAddress<ErrorAction::Recover, AccessType::Load, 0>(p); 4550b57cec5SDimitry Andric } 4560b57cec5SDimitry Andric void __hwasan_load2_noabort(uptr p) { 4570b57cec5SDimitry Andric CheckAddress<ErrorAction::Recover, AccessType::Load, 1>(p); 4580b57cec5SDimitry Andric } 4590b57cec5SDimitry Andric void __hwasan_load4_noabort(uptr p) { 4600b57cec5SDimitry Andric CheckAddress<ErrorAction::Recover, AccessType::Load, 2>(p); 4610b57cec5SDimitry Andric } 4620b57cec5SDimitry Andric void __hwasan_load8_noabort(uptr p) { 4630b57cec5SDimitry Andric CheckAddress<ErrorAction::Recover, AccessType::Load, 3>(p); 4640b57cec5SDimitry Andric } 4650b57cec5SDimitry Andric void __hwasan_load16_noabort(uptr p) { 4660b57cec5SDimitry Andric CheckAddress<ErrorAction::Recover, AccessType::Load, 4>(p); 4670b57cec5SDimitry Andric } 4680b57cec5SDimitry Andric 4690b57cec5SDimitry Andric void __hwasan_storeN(uptr p, uptr sz) { 4700b57cec5SDimitry Andric CheckAddressSized<ErrorAction::Abort, AccessType::Store>(p, sz); 4710b57cec5SDimitry Andric } 4720b57cec5SDimitry Andric void __hwasan_store1(uptr p) { 4730b57cec5SDimitry Andric CheckAddress<ErrorAction::Abort, AccessType::Store, 0>(p); 4740b57cec5SDimitry Andric } 4750b57cec5SDimitry Andric void __hwasan_store2(uptr p) { 4760b57cec5SDimitry Andric CheckAddress<ErrorAction::Abort, AccessType::Store, 1>(p); 4770b57cec5SDimitry Andric } 4780b57cec5SDimitry Andric void __hwasan_store4(uptr p) { 4790b57cec5SDimitry Andric CheckAddress<ErrorAction::Abort, AccessType::Store, 2>(p); 4800b57cec5SDimitry Andric } 4810b57cec5SDimitry Andric void __hwasan_store8(uptr p) { 4820b57cec5SDimitry Andric CheckAddress<ErrorAction::Abort, AccessType::Store, 3>(p); 4830b57cec5SDimitry Andric } 4840b57cec5SDimitry Andric void __hwasan_store16(uptr p) { 4850b57cec5SDimitry Andric CheckAddress<ErrorAction::Abort, AccessType::Store, 4>(p); 4860b57cec5SDimitry Andric } 4870b57cec5SDimitry Andric 4880b57cec5SDimitry Andric void __hwasan_storeN_noabort(uptr p, uptr sz) { 4890b57cec5SDimitry Andric CheckAddressSized<ErrorAction::Recover, AccessType::Store>(p, sz); 4900b57cec5SDimitry Andric } 4910b57cec5SDimitry Andric void __hwasan_store1_noabort(uptr p) { 4920b57cec5SDimitry Andric CheckAddress<ErrorAction::Recover, AccessType::Store, 0>(p); 4930b57cec5SDimitry Andric } 4940b57cec5SDimitry Andric void __hwasan_store2_noabort(uptr p) { 4950b57cec5SDimitry Andric CheckAddress<ErrorAction::Recover, AccessType::Store, 1>(p); 4960b57cec5SDimitry Andric } 4970b57cec5SDimitry Andric void __hwasan_store4_noabort(uptr p) { 4980b57cec5SDimitry Andric CheckAddress<ErrorAction::Recover, AccessType::Store, 2>(p); 4990b57cec5SDimitry Andric } 5000b57cec5SDimitry Andric void __hwasan_store8_noabort(uptr p) { 5010b57cec5SDimitry Andric CheckAddress<ErrorAction::Recover, AccessType::Store, 3>(p); 5020b57cec5SDimitry Andric } 5030b57cec5SDimitry Andric void __hwasan_store16_noabort(uptr p) { 5040b57cec5SDimitry Andric CheckAddress<ErrorAction::Recover, AccessType::Store, 4>(p); 5050b57cec5SDimitry Andric } 5060b57cec5SDimitry Andric 5070b57cec5SDimitry Andric void __hwasan_tag_memory(uptr p, u8 tag, uptr sz) { 5080b57cec5SDimitry Andric TagMemoryAligned(p, sz, tag); 5090b57cec5SDimitry Andric } 5100b57cec5SDimitry Andric 5110b57cec5SDimitry Andric uptr __hwasan_tag_pointer(uptr p, u8 tag) { 5120b57cec5SDimitry Andric return AddTagToPointer(p, tag); 5130b57cec5SDimitry Andric } 5140b57cec5SDimitry Andric 5150b57cec5SDimitry Andric void __hwasan_handle_longjmp(const void *sp_dst) { 5160b57cec5SDimitry Andric uptr dst = (uptr)sp_dst; 5170b57cec5SDimitry Andric // HWASan does not support tagged SP. 5180b57cec5SDimitry Andric CHECK(GetTagFromPointer(dst) == 0); 5190b57cec5SDimitry Andric 5200b57cec5SDimitry Andric uptr sp = (uptr)__builtin_frame_address(0); 5210b57cec5SDimitry Andric static const uptr kMaxExpectedCleanupSize = 64 << 20; // 64M 5220b57cec5SDimitry Andric if (dst < sp || dst - sp > kMaxExpectedCleanupSize) { 5230b57cec5SDimitry Andric Report( 5240b57cec5SDimitry Andric "WARNING: HWASan is ignoring requested __hwasan_handle_longjmp: " 5250b57cec5SDimitry Andric "stack top: %p; target %p; distance: %p (%zd)\n" 5260b57cec5SDimitry Andric "False positive error reports may follow\n", 5270b57cec5SDimitry Andric (void *)sp, (void *)dst, dst - sp); 5280b57cec5SDimitry Andric return; 5290b57cec5SDimitry Andric } 5300b57cec5SDimitry Andric TagMemory(sp, dst - sp, 0); 5310b57cec5SDimitry Andric } 5320b57cec5SDimitry Andric 5330b57cec5SDimitry Andric void __hwasan_handle_vfork(const void *sp_dst) { 5340b57cec5SDimitry Andric uptr sp = (uptr)sp_dst; 5350b57cec5SDimitry Andric Thread *t = GetCurrentThread(); 5360b57cec5SDimitry Andric CHECK(t); 5370b57cec5SDimitry Andric uptr top = t->stack_top(); 5380b57cec5SDimitry Andric uptr bottom = t->stack_bottom(); 5390b57cec5SDimitry Andric if (top == 0 || bottom == 0 || sp < bottom || sp >= top) { 5400b57cec5SDimitry Andric Report( 5410b57cec5SDimitry Andric "WARNING: HWASan is ignoring requested __hwasan_handle_vfork: " 5420b57cec5SDimitry Andric "stack top: %zx; current %zx; bottom: %zx \n" 5430b57cec5SDimitry Andric "False positive error reports may follow\n", 5440b57cec5SDimitry Andric top, sp, bottom); 5450b57cec5SDimitry Andric return; 5460b57cec5SDimitry Andric } 5470b57cec5SDimitry Andric TagMemory(bottom, sp - bottom, 0); 5480b57cec5SDimitry Andric } 5490b57cec5SDimitry Andric 5500b57cec5SDimitry Andric extern "C" void *__hwasan_extra_spill_area() { 5510b57cec5SDimitry Andric Thread *t = GetCurrentThread(); 5520b57cec5SDimitry Andric return &t->vfork_spill(); 5530b57cec5SDimitry Andric } 5540b57cec5SDimitry Andric 5550b57cec5SDimitry Andric void __hwasan_print_memory_usage() { 556*fe6060f1SDimitry Andric InternalScopedString s; 5570b57cec5SDimitry Andric HwasanFormatMemoryUsage(s); 5580b57cec5SDimitry Andric Printf("%s\n", s.data()); 5590b57cec5SDimitry Andric } 5600b57cec5SDimitry Andric 561*fe6060f1SDimitry Andric static const u8 kFallbackTag = 0xBB & kTagMask; 5620b57cec5SDimitry Andric 5630b57cec5SDimitry Andric u8 __hwasan_generate_tag() { 5640b57cec5SDimitry Andric Thread *t = GetCurrentThread(); 5650b57cec5SDimitry Andric if (!t) return kFallbackTag; 5660b57cec5SDimitry Andric return t->GenerateRandomTag(); 5670b57cec5SDimitry Andric } 5680b57cec5SDimitry Andric 5690b57cec5SDimitry Andric #if !SANITIZER_SUPPORTS_WEAK_HOOKS 5700b57cec5SDimitry Andric extern "C" { 5710b57cec5SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE 5720b57cec5SDimitry Andric const char* __hwasan_default_options() { return ""; } 5730b57cec5SDimitry Andric } // extern "C" 5740b57cec5SDimitry Andric #endif 5750b57cec5SDimitry Andric 5760b57cec5SDimitry Andric extern "C" { 5770b57cec5SDimitry Andric SANITIZER_INTERFACE_ATTRIBUTE 5780b57cec5SDimitry Andric void __sanitizer_print_stack_trace() { 5790b57cec5SDimitry Andric GET_FATAL_STACK_TRACE_PC_BP(StackTrace::GetCurrentPc(), GET_CURRENT_FRAME()); 5800b57cec5SDimitry Andric stack.Print(); 5810b57cec5SDimitry Andric } 582*fe6060f1SDimitry Andric 583*fe6060f1SDimitry Andric // Entry point for interoperability between __hwasan_tag_mismatch (ASM) and the 584*fe6060f1SDimitry Andric // rest of the mismatch handling code (C++). 585*fe6060f1SDimitry Andric void __hwasan_tag_mismatch4(uptr addr, uptr access_info, uptr *registers_frame, 586*fe6060f1SDimitry Andric size_t outsize) { 587*fe6060f1SDimitry Andric __hwasan::HwasanTagMismatch(addr, access_info, registers_frame, outsize); 588*fe6060f1SDimitry Andric } 589*fe6060f1SDimitry Andric 5900b57cec5SDimitry Andric } // extern "C" 591