asan_rtl.cc revision a4ccf878e464d29a4a18756c5c4f626dc530a12e
1//===-- asan_rtl.cc ---------------------------------------------*- C++ -*-===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file is a part of AddressSanitizer, an address sanity checker.
11//
12// Main file of the ASan run-time library.
13//===----------------------------------------------------------------------===//
14#include "asan_allocator.h"
15#include "asan_interceptors.h"
16#include "asan_interface.h"
17#include "asan_internal.h"
18#include "asan_lock.h"
19#include "asan_mac.h"
20#include "asan_mapping.h"
21#include "asan_procmaps.h"
22#include "asan_stack.h"
23#include "asan_stats.h"
24#include "asan_thread.h"
25#include "asan_thread_registry.h"
26
27namespace __asan {
28
29// -------------------------- Flags ------------------------- {{{1
30static const size_t kMallocContextSize = 30;
31static int    FLAG_atexit;
32bool   FLAG_fast_unwind = true;
33
34size_t FLAG_redzone;  // power of two, >= 32
35size_t FLAG_quarantine_size;
36int    FLAG_demangle;
37bool   FLAG_symbolize;
38int    FLAG_v;
39int    FLAG_debug;
40bool   FLAG_poison_shadow;
41int    FLAG_report_globals;
42size_t FLAG_malloc_context_size = kMallocContextSize;
43uintptr_t FLAG_large_malloc;
44bool   FLAG_handle_segv;
45bool   FLAG_replace_str;
46bool   FLAG_replace_intrin;
47bool   FLAG_replace_cfallocator;  // Used on Mac only.
48size_t FLAG_max_malloc_fill_size = 0;
49bool   FLAG_use_fake_stack;
50int    FLAG_exitcode = EXIT_FAILURE;
51bool   FLAG_allow_user_poisoning;
52
53// -------------------------- Globals --------------------- {{{1
54int asan_inited;
55bool asan_init_is_running;
56
57// -------------------------- Misc ---------------- {{{1
58void ShowStatsAndAbort() {
59  __asan_print_accumulated_stats();
60  ASAN_DIE;
61}
62
63static void PrintBytes(const char *before, uintptr_t *a) {
64  uint8_t *bytes = (uint8_t*)a;
65  size_t byte_num = (__WORDSIZE) / 8;
66  Printf("%s%p:", before, (uintptr_t)a);
67  for (size_t i = 0; i < byte_num; i++) {
68    Printf(" %lx%lx", bytes[i] >> 4, bytes[i] & 15);
69  }
70  Printf("\n");
71}
72
73ssize_t ReadFileToBuffer(const char *file_name, char **buff,
74                         size_t *buff_size, size_t max_len) {
75  const size_t kMinFileLen = kPageSize;
76  ssize_t read_len = -1;
77  *buff = 0;
78  *buff_size = 0;
79  // The files we usually open are not seekable, so try different buffer sizes.
80  for (size_t size = kMinFileLen; size <= max_len; size *= 2) {
81    int fd = AsanOpenReadonly(file_name);
82    if (fd < 0) return -1;
83    AsanUnmapOrDie(*buff, *buff_size);
84    *buff = (char*)AsanMmapSomewhereOrDie(size, __FUNCTION__);
85    *buff_size = size;
86    read_len = AsanRead(fd, *buff, size);
87    AsanClose(fd);
88    if (read_len < size)  // We've read the whole file.
89      break;
90  }
91  return read_len;
92}
93
94// Like getenv, but reads env directly from /proc and does not use libc.
95// This function should be called first inside __asan_init.
96static const char* GetEnvFromProcSelfEnviron(const char* name) {
97  static char *environ;
98  static ssize_t len;
99  static bool inited;
100  if (!inited) {
101    inited = true;
102    size_t environ_size;
103    len = ReadFileToBuffer("/proc/self/environ",
104                           &environ, &environ_size, 1 << 20);
105  }
106  if (!environ || len <= 0) return NULL;
107  size_t namelen = internal_strlen(name);
108  const char *p = environ;
109  while (*p != '\0') {  // will happen at the \0\0 that terminates the buffer
110    // proc file has the format NAME=value\0NAME=value\0NAME=value\0...
111    const char* endp =
112        (char*)internal_memchr(p, '\0', len - (p - environ));
113    if (endp == NULL)  // this entry isn't NUL terminated
114      return NULL;
115    else if (!internal_memcmp(p, name, namelen) && p[namelen] == '=')  // Match.
116      return p + namelen + 1;  // point after =
117    p = endp + 1;
118  }
119  return NULL;  // Not found.
120}
121
122// ---------------------- mmap -------------------- {{{1
123void OutOfMemoryMessageAndDie(const char *mem_type, size_t size) {
124  Report("ERROR: AddressSanitizer failed to allocate "
125         "0x%lx (%ld) bytes of %s\n",
126         size, size, mem_type);
127  PRINT_CURRENT_STACK();
128  ShowStatsAndAbort();
129}
130
131// Reserve memory range [beg, end].
132static void ReserveShadowMemoryRange(uintptr_t beg, uintptr_t end) {
133  CHECK((beg % kPageSize) == 0);
134  CHECK(((end + 1) % kPageSize) == 0);
135  size_t size = end - beg + 1;
136  void *res = AsanMmapFixedNoReserve(beg, size);
137  CHECK(res == (void*)beg && "ReserveShadowMemoryRange failed");
138}
139
140// ---------------------- LowLevelAllocator ------------- {{{1
141void *LowLevelAllocator::Allocate(size_t size) {
142  CHECK((size & (size - 1)) == 0 && "size must be a power of two");
143  if (allocated_end_ - allocated_current_ < size) {
144    size_t size_to_allocate = Max(size, kPageSize);
145    allocated_current_ =
146        (char*)AsanMmapSomewhereOrDie(size_to_allocate, __FUNCTION__);
147    allocated_end_ = allocated_current_ + size_to_allocate;
148    PoisonShadow((uintptr_t)allocated_current_, size_to_allocate,
149                 kAsanInternalHeapMagic);
150  }
151  CHECK(allocated_end_ - allocated_current_ >= size);
152  void *res = allocated_current_;
153  allocated_current_ += size;
154  return res;
155}
156
157// ---------------------- DescribeAddress -------------------- {{{1
158static bool DescribeStackAddress(uintptr_t addr, uintptr_t access_size) {
159  AsanThread *t = asanThreadRegistry().FindThreadByStackAddress(addr);
160  if (!t) return false;
161  const intptr_t kBufSize = 4095;
162  char buf[kBufSize];
163  uintptr_t offset = 0;
164  const char *frame_descr = t->GetFrameNameByAddr(addr, &offset);
165  // This string is created by the compiler and has the following form:
166  // "FunctioName n alloc_1 alloc_2 ... alloc_n"
167  // where alloc_i looks like "offset size len ObjectName ".
168  CHECK(frame_descr);
169  // Report the function name and the offset.
170  const char *name_end = real_strchr(frame_descr, ' ');
171  CHECK(name_end);
172  buf[0] = 0;
173  internal_strncat(buf, frame_descr,
174                   Min(kBufSize,
175                       static_cast<intptr_t>(name_end - frame_descr)));
176  Printf("Address %p is located at offset %ld "
177         "in frame <%s> of T%d's stack:\n",
178         addr, offset, buf, t->tid());
179  // Report the number of stack objects.
180  char *p;
181  size_t n_objects = strtol(name_end, &p, 10);
182  CHECK(n_objects > 0);
183  Printf("  This frame has %ld object(s):\n", n_objects);
184  // Report all objects in this frame.
185  for (size_t i = 0; i < n_objects; i++) {
186    size_t beg, size;
187    intptr_t len;
188    beg  = strtol(p, &p, 10);
189    size = strtol(p, &p, 10);
190    len  = strtol(p, &p, 10);
191    if (beg <= 0 || size <= 0 || len < 0 || *p != ' ') {
192      Printf("AddressSanitizer can't parse the stack frame descriptor: |%s|\n",
193             frame_descr);
194      break;
195    }
196    p++;
197    buf[0] = 0;
198    internal_strncat(buf, p, Min(kBufSize, len));
199    p += len;
200    Printf("    [%ld, %ld) '%s'\n", beg, beg + size, buf);
201  }
202  Printf("HINT: this may be a false positive if your program uses "
203         "some custom stack unwind mechanism\n"
204         "      (longjmp and C++ exceptions *are* supported)\n");
205  t->summary()->Announce();
206  return true;
207}
208
209__attribute__((noinline))
210static void DescribeAddress(uintptr_t addr, uintptr_t access_size) {
211  // Check if this is a global.
212  if (DescribeAddrIfGlobal(addr))
213    return;
214
215  if (DescribeStackAddress(addr, access_size))
216    return;
217
218  // finally, check if this is a heap.
219  DescribeHeapAddress(addr, access_size);
220}
221
222// -------------------------- Run-time entry ------------------- {{{1
223// exported functions
224#define ASAN_REPORT_ERROR(type, is_write, size)                     \
225extern "C" void __asan_report_ ## type ## size(uintptr_t addr)      \
226  __attribute__((visibility("default"))) __attribute__((noinline)); \
227extern "C" void __asan_report_ ## type ## size(uintptr_t addr) {    \
228  GET_BP_PC_SP;                                                     \
229  __asan_report_error(pc, bp, sp, addr, is_write, size);            \
230}
231
232ASAN_REPORT_ERROR(load, false, 1)
233ASAN_REPORT_ERROR(load, false, 2)
234ASAN_REPORT_ERROR(load, false, 4)
235ASAN_REPORT_ERROR(load, false, 8)
236ASAN_REPORT_ERROR(load, false, 16)
237ASAN_REPORT_ERROR(store, true, 1)
238ASAN_REPORT_ERROR(store, true, 2)
239ASAN_REPORT_ERROR(store, true, 4)
240ASAN_REPORT_ERROR(store, true, 8)
241ASAN_REPORT_ERROR(store, true, 16)
242
243// Force the linker to keep the symbols for various ASan interface functions.
244// We want to keep those in the executable in order to let the instrumented
245// dynamic libraries access the symbol even if it is not used by the executable
246// itself. This should help if the build system is removing dead code at link
247// time.
248static void force_interface_symbols() {
249  volatile int fake_condition = 0;  // prevent dead condition elimination.
250  if (fake_condition) {
251    __asan_report_load1(NULL);
252    __asan_report_load2(NULL);
253    __asan_report_load4(NULL);
254    __asan_report_load8(NULL);
255    __asan_report_load16(NULL);
256    __asan_report_store1(NULL);
257    __asan_report_store2(NULL);
258    __asan_report_store4(NULL);
259    __asan_report_store8(NULL);
260    __asan_report_store16(NULL);
261    __asan_register_global(0, 0, NULL);
262    __asan_register_globals(NULL, 0);
263    __asan_unregister_globals(NULL, 0);
264  }
265}
266
267// -------------------------- Init ------------------- {{{1
268static int64_t IntFlagValue(const char *flags, const char *flag,
269                            int64_t default_val) {
270  if (!flags) return default_val;
271  const char *str = internal_strstr(flags, flag);
272  if (!str) return default_val;
273  return atoll(str + internal_strlen(flag));
274}
275
276static void asan_atexit() {
277  Printf("AddressSanitizer exit stats:\n");
278  __asan_print_accumulated_stats();
279}
280
281void CheckFailed(const char *cond, const char *file, int line) {
282  Report("CHECK failed: %s at %s:%d\n", cond, file, line);
283  PRINT_CURRENT_STACK();
284  ShowStatsAndAbort();
285}
286
287}  // namespace __asan
288
289// ---------------------- Interface ---------------- {{{1
290using namespace __asan;  // NOLINT
291
292int __asan_set_error_exit_code(int exit_code) {
293  int old = FLAG_exitcode;
294  FLAG_exitcode = exit_code;
295  return old;
296}
297
298void __asan_report_error(uintptr_t pc, uintptr_t bp, uintptr_t sp,
299                         uintptr_t addr, bool is_write, size_t access_size) {
300  // Do not print more than one report, otherwise they will mix up.
301  static int num_calls = 0;
302  if (AtomicInc(&num_calls) > 1) return;
303
304  Printf("=================================================================\n");
305  const char *bug_descr = "unknown-crash";
306  if (AddrIsInMem(addr)) {
307    uint8_t *shadow_addr = (uint8_t*)MemToShadow(addr);
308    // If we are accessing 16 bytes, look at the second shadow byte.
309    if (*shadow_addr == 0 && access_size > SHADOW_GRANULARITY)
310      shadow_addr++;
311    // If we are in the partial right redzone, look at the next shadow byte.
312    if (*shadow_addr > 0 && *shadow_addr < 128)
313      shadow_addr++;
314    switch (*shadow_addr) {
315      case kAsanHeapLeftRedzoneMagic:
316      case kAsanHeapRightRedzoneMagic:
317        bug_descr = "heap-buffer-overflow";
318        break;
319      case kAsanHeapFreeMagic:
320        bug_descr = "heap-use-after-free";
321        break;
322      case kAsanStackLeftRedzoneMagic:
323        bug_descr = "stack-buffer-underflow";
324        break;
325      case kAsanStackMidRedzoneMagic:
326      case kAsanStackRightRedzoneMagic:
327      case kAsanStackPartialRedzoneMagic:
328        bug_descr = "stack-buffer-overflow";
329        break;
330      case kAsanStackAfterReturnMagic:
331        bug_descr = "stack-use-after-return";
332        break;
333      case kAsanUserPoisonedMemoryMagic:
334        bug_descr = "use-after-poison";
335        break;
336      case kAsanGlobalRedzoneMagic:
337        bug_descr = "global-buffer-overflow";
338        break;
339    }
340  }
341
342  AsanThread *curr_thread = asanThreadRegistry().GetCurrent();
343  int curr_tid = asanThreadRegistry().GetCurrentTidOrMinusOne();
344
345  if (curr_thread) {
346    // We started reporting an error message. Stop using the fake stack
347    // in case we will call an instrumented function from a symbolizer.
348    curr_thread->fake_stack().StopUsingFakeStack();
349  }
350
351  Report("ERROR: AddressSanitizer %s on address "
352         "%p at pc 0x%lx bp 0x%lx sp 0x%lx\n",
353         bug_descr, addr, pc, bp, sp);
354
355  Printf("%s of size %d at %p thread T%d\n",
356         access_size ? (is_write ? "WRITE" : "READ") : "ACCESS",
357         access_size, addr, curr_tid);
358
359  if (FLAG_debug) {
360    PrintBytes("PC: ", (uintptr_t*)pc);
361  }
362
363  GET_STACK_TRACE_WITH_PC_AND_BP(kStackTraceMax,
364                                 false,  // FLAG_fast_unwind,
365                                 pc, bp);
366  stack.PrintStack();
367
368  CHECK(AddrIsInMem(addr));
369
370  DescribeAddress(addr, access_size);
371
372  uintptr_t shadow_addr = MemToShadow(addr);
373  Report("ABORTING\n");
374  __asan_print_accumulated_stats();
375  Printf("Shadow byte and word:\n");
376  Printf("  %p: %x\n", shadow_addr, *(unsigned char*)shadow_addr);
377  uintptr_t aligned_shadow = shadow_addr & ~(kWordSize - 1);
378  PrintBytes("  ", (uintptr_t*)(aligned_shadow));
379  Printf("More shadow bytes:\n");
380  PrintBytes("  ", (uintptr_t*)(aligned_shadow-4*kWordSize));
381  PrintBytes("  ", (uintptr_t*)(aligned_shadow-3*kWordSize));
382  PrintBytes("  ", (uintptr_t*)(aligned_shadow-2*kWordSize));
383  PrintBytes("  ", (uintptr_t*)(aligned_shadow-1*kWordSize));
384  PrintBytes("=>", (uintptr_t*)(aligned_shadow+0*kWordSize));
385  PrintBytes("  ", (uintptr_t*)(aligned_shadow+1*kWordSize));
386  PrintBytes("  ", (uintptr_t*)(aligned_shadow+2*kWordSize));
387  PrintBytes("  ", (uintptr_t*)(aligned_shadow+3*kWordSize));
388  PrintBytes("  ", (uintptr_t*)(aligned_shadow+4*kWordSize));
389  ASAN_DIE;
390}
391
392void __asan_init() {
393  if (asan_inited) return;
394  asan_init_is_running = true;
395
396  // Make sure we are not statically linked.
397  AsanDoesNotSupportStaticLinkage();
398
399  // flags
400  const char *options = GetEnvFromProcSelfEnviron("ASAN_OPTIONS");
401  FLAG_malloc_context_size =
402      IntFlagValue(options, "malloc_context_size=", kMallocContextSize);
403  CHECK(FLAG_malloc_context_size <= kMallocContextSize);
404
405  FLAG_max_malloc_fill_size =
406      IntFlagValue(options, "max_malloc_fill_size=", 0);
407
408  FLAG_v = IntFlagValue(options, "verbosity=", 0);
409
410  FLAG_redzone = IntFlagValue(options, "redzone=", 128);
411  CHECK(FLAG_redzone >= 32);
412  CHECK((FLAG_redzone & (FLAG_redzone - 1)) == 0);
413
414  FLAG_atexit = IntFlagValue(options, "atexit=", 0);
415  FLAG_poison_shadow = IntFlagValue(options, "poison_shadow=", 1);
416  FLAG_report_globals = IntFlagValue(options, "report_globals=", 1);
417  FLAG_handle_segv = IntFlagValue(options, "handle_segv=", ASAN_NEEDS_SEGV);
418  FLAG_symbolize = IntFlagValue(options, "symbolize=", 1);
419  FLAG_demangle = IntFlagValue(options, "demangle=", 1);
420  FLAG_debug = IntFlagValue(options, "debug=", 0);
421  FLAG_replace_cfallocator = IntFlagValue(options, "replace_cfallocator=", 1);
422  FLAG_fast_unwind = IntFlagValue(options, "fast_unwind=", 1);
423  FLAG_replace_str = IntFlagValue(options, "replace_str=", 1);
424  FLAG_replace_intrin = IntFlagValue(options, "replace_intrin=", 1);
425  FLAG_use_fake_stack = IntFlagValue(options, "use_fake_stack=", 1);
426  FLAG_exitcode = IntFlagValue(options, "exitcode=", EXIT_FAILURE);
427  FLAG_allow_user_poisoning = IntFlagValue(options,
428                                           "allow_user_poisoning=", 1);
429
430  if (FLAG_atexit) {
431    atexit(asan_atexit);
432  }
433
434  FLAG_quarantine_size =
435      IntFlagValue(options, "quarantine_size=", 1UL << 28);
436
437  // interceptors
438  InitializeAsanInterceptors();
439
440  ReplaceSystemMalloc();
441  InstallSignalHandlers();
442
443  if (FLAG_v) {
444    Printf("|| `[%p, %p]` || HighMem    ||\n", kHighMemBeg, kHighMemEnd);
445    Printf("|| `[%p, %p]` || HighShadow ||\n",
446           kHighShadowBeg, kHighShadowEnd);
447    Printf("|| `[%p, %p]` || ShadowGap  ||\n",
448           kShadowGapBeg, kShadowGapEnd);
449    Printf("|| `[%p, %p]` || LowShadow  ||\n",
450           kLowShadowBeg, kLowShadowEnd);
451    Printf("|| `[%p, %p]` || LowMem     ||\n", kLowMemBeg, kLowMemEnd);
452    Printf("MemToShadow(shadow): %p %p %p %p\n",
453           MEM_TO_SHADOW(kLowShadowBeg),
454           MEM_TO_SHADOW(kLowShadowEnd),
455           MEM_TO_SHADOW(kHighShadowBeg),
456           MEM_TO_SHADOW(kHighShadowEnd));
457    Printf("red_zone=%ld\n", FLAG_redzone);
458    Printf("malloc_context_size=%ld\n", (int)FLAG_malloc_context_size);
459    Printf("fast_unwind=%d\n", (int)FLAG_fast_unwind);
460
461    Printf("SHADOW_SCALE: %lx\n", SHADOW_SCALE);
462    Printf("SHADOW_GRANULARITY: %lx\n", SHADOW_GRANULARITY);
463    Printf("SHADOW_OFFSET: %lx\n", SHADOW_OFFSET);
464    CHECK(SHADOW_SCALE >= 3 && SHADOW_SCALE <= 7);
465  }
466
467  if (__WORDSIZE == 64) {
468    // Disable core dumper -- it makes little sense to dump 16T+ core.
469    AsanDisableCoreDumper();
470  }
471
472  {
473    if (kLowShadowBeg != kLowShadowEnd) {
474      // mmap the low shadow plus one page.
475      ReserveShadowMemoryRange(kLowShadowBeg - kPageSize, kLowShadowEnd);
476    }
477    // mmap the high shadow.
478    ReserveShadowMemoryRange(kHighShadowBeg, kHighShadowEnd);
479    // protect the gap
480    void *prot = AsanMprotect(kShadowGapBeg, kShadowGapEnd - kShadowGapBeg + 1);
481    CHECK(prot == (void*)kShadowGapBeg);
482  }
483
484  // On Linux AsanThread::ThreadStart() calls malloc() that's why asan_inited
485  // should be set to 1 prior to initializing the threads.
486  asan_inited = 1;
487  asan_init_is_running = false;
488
489  asanThreadRegistry().Init();
490  asanThreadRegistry().GetMain()->ThreadStart();
491  force_interface_symbols();  // no-op.
492
493  if (FLAG_v) {
494    Report("AddressSanitizer Init done\n");
495  }
496}
497