1 //===-- hwasan.cpp --------------------------------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // This file is a part of HWAddressSanitizer.
11 // HWAddressSanitizer runtime.
12 //===----------------------------------------------------------------------===//
15 #include "hwasan_checks.h"
16 #include "hwasan_dynamic_shadow.h"
17 #include "hwasan_poisoning.h"
18 #include "hwasan_report.h"
19 #include "hwasan_thread.h"
20 #include "hwasan_thread_list.h"
21 #include "sanitizer_common/sanitizer_atomic.h"
22 #include "sanitizer_common/sanitizer_common.h"
23 #include "sanitizer_common/sanitizer_flag_parser.h"
24 #include "sanitizer_common/sanitizer_flags.h"
25 #include "sanitizer_common/sanitizer_libc.h"
26 #include "sanitizer_common/sanitizer_procmaps.h"
27 #include "sanitizer_common/sanitizer_stackdepot.h"
28 #include "sanitizer_common/sanitizer_stacktrace.h"
29 #include "sanitizer_common/sanitizer_symbolizer.h"
30 #include "ubsan/ubsan_flags.h"
31 #include "ubsan/ubsan_init.h"
33 // ACHTUNG! No system header includes in this file.
35 using namespace __sanitizer;
39 void EnterSymbolizer() {
40 Thread *t = GetCurrentThread();
44 void ExitSymbolizer() {
45 Thread *t = GetCurrentThread();
49 bool IsInSymbolizer() {
50 Thread *t = GetCurrentThread();
51 return t && t->InSymbolizer();
54 static Flags hwasan_flags;
60 int hwasan_inited = 0;
61 int hwasan_instrumentation_inited = 0;
62 bool hwasan_init_is_running;
64 int hwasan_report_count = 0;
66 void Flags::SetDefaults() {
67 #define HWASAN_FLAG(Type, Name, DefaultValue, Description) Name = DefaultValue;
68 #include "hwasan_flags.inc"
72 static void RegisterHwasanFlags(FlagParser *parser, Flags *f) {
73 #define HWASAN_FLAG(Type, Name, DefaultValue, Description) \
74 RegisterFlag(parser, #Name, Description, &f->Name);
75 #include "hwasan_flags.inc"
79 static void InitializeFlags() {
80 SetCommonFlagsDefaults();
83 cf.CopyFrom(*common_flags());
84 cf.external_symbolizer_path = GetEnv("HWASAN_SYMBOLIZER_PATH");
85 cf.malloc_context_size = 20;
86 cf.handle_ioctl = true;
87 // FIXME: test and enable.
88 cf.check_printf = false;
89 cf.intercept_tls_get_addr = true;
91 // 8 shadow pages ~512kB, small enough to cover common stack sizes.
92 cf.clear_shadow_mmap_threshold = 4096 * (SANITIZER_ANDROID ? 2 : 8);
93 // Sigtrap is used in error reporting.
94 cf.handle_sigtrap = kHandleSignalExclusive;
97 // Let platform handle other signals. It is better at reporting them then we
99 cf.handle_segv = kHandleSignalNo;
100 cf.handle_sigbus = kHandleSignalNo;
101 cf.handle_abort = kHandleSignalNo;
102 cf.handle_sigill = kHandleSignalNo;
103 cf.handle_sigfpe = kHandleSignalNo;
105 OverrideCommonFlags(cf);
112 RegisterHwasanFlags(&parser, f);
113 RegisterCommonFlags(&parser);
115 #if HWASAN_CONTAINS_UBSAN
116 __ubsan::Flags *uf = __ubsan::flags();
119 FlagParser ubsan_parser;
120 __ubsan::RegisterUbsanFlags(&ubsan_parser, uf);
121 RegisterCommonFlags(&ubsan_parser);
124 // Override from user-specified string.
125 if (__hwasan_default_options)
126 parser.ParseString(__hwasan_default_options());
127 #if HWASAN_CONTAINS_UBSAN
128 const char *ubsan_default_options = __ubsan::MaybeCallUbsanDefaultOptions();
129 ubsan_parser.ParseString(ubsan_default_options);
132 parser.ParseStringFromEnv("HWASAN_OPTIONS");
133 #if HWASAN_CONTAINS_UBSAN
134 ubsan_parser.ParseStringFromEnv("UBSAN_OPTIONS");
137 InitializeCommonFlags();
139 if (Verbosity()) ReportUnrecognizedFlags();
141 if (common_flags()->help) parser.PrintFlagDescriptions();
144 static void HWAsanCheckFailed(const char *file, int line, const char *cond,
146 Report("HWAddressSanitizer CHECK failed: %s:%d \"%s\" (0x%zx, 0x%zx)\n", file,
147 line, cond, (uptr)v1, (uptr)v2);
148 PRINT_CURRENT_STACK_CHECK();
152 static constexpr uptr kMemoryUsageBufferSize = 4096;
154 static void HwasanFormatMemoryUsage(InternalScopedString &s) {
155 HwasanThreadList &thread_list = hwasanThreadList();
156 auto thread_stats = thread_list.GetThreadStats();
157 auto *sds = StackDepotGetStats();
158 AllocatorStatCounters asc;
159 GetAllocatorStats(asc);
161 "HWASAN pid: %d rss: %zd threads: %zd stacks: %zd"
162 " thr_aux: %zd stack_depot: %zd uniq_stacks: %zd"
164 internal_getpid(), GetRSS(), thread_stats.n_live_threads,
165 thread_stats.total_stack_size,
166 thread_stats.n_live_threads * thread_list.MemoryUsedPerThread(),
167 sds->allocated, sds->n_uniq_ids, asc[AllocatorStatMapped]);
170 #if SANITIZER_ANDROID
171 static char *memory_usage_buffer = nullptr;
173 static void InitMemoryUsage() {
174 memory_usage_buffer =
175 (char *)MmapOrDie(kMemoryUsageBufferSize, "memory usage string");
176 CHECK(memory_usage_buffer);
177 memory_usage_buffer[0] = '\0';
178 DecorateMapping((uptr)memory_usage_buffer, kMemoryUsageBufferSize,
179 memory_usage_buffer);
182 void UpdateMemoryUsage() {
183 if (!flags()->export_memory_stats)
185 if (!memory_usage_buffer)
187 InternalScopedString s(kMemoryUsageBufferSize);
188 HwasanFormatMemoryUsage(s);
189 internal_strncpy(memory_usage_buffer, s.data(), kMemoryUsageBufferSize - 1);
190 memory_usage_buffer[kMemoryUsageBufferSize - 1] = '\0';
193 void UpdateMemoryUsage() {}
196 // Prepare to run instrumented code on the main thread.
197 void InitInstrumentation() {
198 if (hwasan_instrumentation_inited) return;
201 Printf("FATAL: HWAddressSanitizer cannot mmap the shadow memory.\n");
207 hwasanThreadList().CreateCurrentThread();
209 hwasan_instrumentation_inited = 1;
212 } // namespace __hwasan
214 void __sanitizer::BufferedStackTrace::UnwindImpl(
215 uptr pc, uptr bp, void *context, bool request_fast, u32 max_depth) {
216 using namespace __hwasan;
217 Thread *t = GetCurrentThread();
219 // the thread is still being created.
223 if (!StackTrace::WillUseFastUnwind(request_fast)) {
224 // Block reports from our interceptors during _Unwind_Backtrace.
225 SymbolizerScope sym_scope;
226 return Unwind(max_depth, pc, bp, context, 0, 0, request_fast);
228 if (StackTrace::WillUseFastUnwind(request_fast))
229 Unwind(max_depth, pc, bp, nullptr, t->stack_top(), t->stack_bottom(), true);
231 Unwind(max_depth, pc, 0, context, 0, 0, false);
236 using namespace __hwasan;
238 uptr __hwasan_shadow_memory_dynamic_address; // Global interface symbol.
240 // This function was used by the old frame descriptor mechanism. We keep it
241 // around to avoid breaking ABI.
242 void __hwasan_init_frames(uptr beg, uptr end) {}
244 void __hwasan_init_static() {
246 InitInstrumentation();
249 void __hwasan_init() {
250 CHECK(!hwasan_init_is_running);
251 if (hwasan_inited) return;
252 hwasan_init_is_running = 1;
253 SanitizerToolName = "HWAddressSanitizer";
260 // Install tool-specific callbacks in sanitizer_common.
261 SetCheckFailedCallback(HWAsanCheckFailed);
263 __sanitizer_set_report_path(common_flags()->log_path);
265 AndroidTestTlsSlot();
267 DisableCoreDumperIfNecessary();
269 InitInstrumentation();
271 // Needs to be called here because flags()->random_tags might not have been
272 // initialized when InitInstrumentation() was called.
273 GetCurrentThread()->InitRandomState();
277 SetPrintfAndReportCallback(AppendToErrorMessageBuffer);
278 // This may call libc -> needs initialized shadow.
281 InitializeInterceptors();
282 InstallDeadlySignalHandlers(HwasanOnDeadlySignal);
283 InstallAtExitHandler(); // Needs __cxa_atexit interceptor.
285 Symbolizer::GetOrInit()->AddHooks(EnterSymbolizer, ExitSymbolizer);
287 InitializeCoverage(common_flags()->coverage, common_flags()->coverage_dir);
290 HwasanTSDThreadInit();
292 HwasanAllocatorInit();
294 #if HWASAN_CONTAINS_UBSAN
295 __ubsan::InitAsPlugin();
298 VPrintf(1, "HWAddressSanitizer init done\n");
300 hwasan_init_is_running = 0;
304 void __hwasan_print_shadow(const void *p, uptr sz) {
305 uptr ptr_raw = UntagAddr(reinterpret_cast<uptr>(p));
306 uptr shadow_first = MemToShadow(ptr_raw);
307 uptr shadow_last = MemToShadow(ptr_raw + sz - 1);
308 Printf("HWASan shadow map for %zx .. %zx (pointer tag %x)\n", ptr_raw,
309 ptr_raw + sz, GetTagFromPointer((uptr)p));
310 for (uptr s = shadow_first; s <= shadow_last; ++s)
311 Printf(" %zx: %x\n", ShadowToMem(s), *(tag_t *)s);
314 sptr __hwasan_test_shadow(const void *p, uptr sz) {
317 tag_t ptr_tag = GetTagFromPointer((uptr)p);
318 uptr ptr_raw = UntagAddr(reinterpret_cast<uptr>(p));
319 uptr shadow_first = MemToShadow(ptr_raw);
320 uptr shadow_last = MemToShadow(ptr_raw + sz - 1);
321 for (uptr s = shadow_first; s <= shadow_last; ++s)
322 if (*(tag_t *)s != ptr_tag) {
323 sptr offset = ShadowToMem(s) - ptr_raw;
324 return offset < 0 ? 0 : offset;
329 u16 __sanitizer_unaligned_load16(const uu16 *p) {
332 u32 __sanitizer_unaligned_load32(const uu32 *p) {
335 u64 __sanitizer_unaligned_load64(const uu64 *p) {
338 void __sanitizer_unaligned_store16(uu16 *p, u16 x) {
341 void __sanitizer_unaligned_store32(uu32 *p, u32 x) {
344 void __sanitizer_unaligned_store64(uu64 *p, u64 x) {
348 void __hwasan_loadN(uptr p, uptr sz) {
349 CheckAddressSized<ErrorAction::Abort, AccessType::Load>(p, sz);
351 void __hwasan_load1(uptr p) {
352 CheckAddress<ErrorAction::Abort, AccessType::Load, 0>(p);
354 void __hwasan_load2(uptr p) {
355 CheckAddress<ErrorAction::Abort, AccessType::Load, 1>(p);
357 void __hwasan_load4(uptr p) {
358 CheckAddress<ErrorAction::Abort, AccessType::Load, 2>(p);
360 void __hwasan_load8(uptr p) {
361 CheckAddress<ErrorAction::Abort, AccessType::Load, 3>(p);
363 void __hwasan_load16(uptr p) {
364 CheckAddress<ErrorAction::Abort, AccessType::Load, 4>(p);
367 void __hwasan_loadN_noabort(uptr p, uptr sz) {
368 CheckAddressSized<ErrorAction::Recover, AccessType::Load>(p, sz);
370 void __hwasan_load1_noabort(uptr p) {
371 CheckAddress<ErrorAction::Recover, AccessType::Load, 0>(p);
373 void __hwasan_load2_noabort(uptr p) {
374 CheckAddress<ErrorAction::Recover, AccessType::Load, 1>(p);
376 void __hwasan_load4_noabort(uptr p) {
377 CheckAddress<ErrorAction::Recover, AccessType::Load, 2>(p);
379 void __hwasan_load8_noabort(uptr p) {
380 CheckAddress<ErrorAction::Recover, AccessType::Load, 3>(p);
382 void __hwasan_load16_noabort(uptr p) {
383 CheckAddress<ErrorAction::Recover, AccessType::Load, 4>(p);
386 void __hwasan_storeN(uptr p, uptr sz) {
387 CheckAddressSized<ErrorAction::Abort, AccessType::Store>(p, sz);
389 void __hwasan_store1(uptr p) {
390 CheckAddress<ErrorAction::Abort, AccessType::Store, 0>(p);
392 void __hwasan_store2(uptr p) {
393 CheckAddress<ErrorAction::Abort, AccessType::Store, 1>(p);
395 void __hwasan_store4(uptr p) {
396 CheckAddress<ErrorAction::Abort, AccessType::Store, 2>(p);
398 void __hwasan_store8(uptr p) {
399 CheckAddress<ErrorAction::Abort, AccessType::Store, 3>(p);
401 void __hwasan_store16(uptr p) {
402 CheckAddress<ErrorAction::Abort, AccessType::Store, 4>(p);
405 void __hwasan_storeN_noabort(uptr p, uptr sz) {
406 CheckAddressSized<ErrorAction::Recover, AccessType::Store>(p, sz);
408 void __hwasan_store1_noabort(uptr p) {
409 CheckAddress<ErrorAction::Recover, AccessType::Store, 0>(p);
411 void __hwasan_store2_noabort(uptr p) {
412 CheckAddress<ErrorAction::Recover, AccessType::Store, 1>(p);
414 void __hwasan_store4_noabort(uptr p) {
415 CheckAddress<ErrorAction::Recover, AccessType::Store, 2>(p);
417 void __hwasan_store8_noabort(uptr p) {
418 CheckAddress<ErrorAction::Recover, AccessType::Store, 3>(p);
420 void __hwasan_store16_noabort(uptr p) {
421 CheckAddress<ErrorAction::Recover, AccessType::Store, 4>(p);
424 void __hwasan_tag_memory(uptr p, u8 tag, uptr sz) {
425 TagMemoryAligned(p, sz, tag);
428 uptr __hwasan_tag_pointer(uptr p, u8 tag) {
429 return AddTagToPointer(p, tag);
432 void __hwasan_handle_longjmp(const void *sp_dst) {
433 uptr dst = (uptr)sp_dst;
434 // HWASan does not support tagged SP.
435 CHECK(GetTagFromPointer(dst) == 0);
437 uptr sp = (uptr)__builtin_frame_address(0);
438 static const uptr kMaxExpectedCleanupSize = 64 << 20; // 64M
439 if (dst < sp || dst - sp > kMaxExpectedCleanupSize) {
441 "WARNING: HWASan is ignoring requested __hwasan_handle_longjmp: "
442 "stack top: %p; target %p; distance: %p (%zd)\n"
443 "False positive error reports may follow\n",
444 (void *)sp, (void *)dst, dst - sp);
447 TagMemory(sp, dst - sp, 0);
450 void __hwasan_handle_vfork(const void *sp_dst) {
451 uptr sp = (uptr)sp_dst;
452 Thread *t = GetCurrentThread();
454 uptr top = t->stack_top();
455 uptr bottom = t->stack_bottom();
456 if (top == 0 || bottom == 0 || sp < bottom || sp >= top) {
458 "WARNING: HWASan is ignoring requested __hwasan_handle_vfork: "
459 "stack top: %zx; current %zx; bottom: %zx \n"
460 "False positive error reports may follow\n",
464 TagMemory(bottom, sp - bottom, 0);
467 extern "C" void *__hwasan_extra_spill_area() {
468 Thread *t = GetCurrentThread();
469 return &t->vfork_spill();
472 void __hwasan_print_memory_usage() {
473 InternalScopedString s(kMemoryUsageBufferSize);
474 HwasanFormatMemoryUsage(s);
475 Printf("%s\n", s.data());
478 static const u8 kFallbackTag = 0xBB;
480 u8 __hwasan_generate_tag() {
481 Thread *t = GetCurrentThread();
482 if (!t) return kFallbackTag;
483 return t->GenerateRandomTag();
486 #if !SANITIZER_SUPPORTS_WEAK_HOOKS
488 SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE
489 const char* __hwasan_default_options() { return ""; }
494 SANITIZER_INTERFACE_ATTRIBUTE
495 void __sanitizer_print_stack_trace() {
496 GET_FATAL_STACK_TRACE_PC_BP(StackTrace::GetCurrentPc(), GET_CURRENT_FRAME());