xref: /llvm-project/compiler-rt/lib/asan/asan_rtl.cpp (revision a0bb2e21c10bebcdb6bc6b8bc18f74dcf7c4b8b2)
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