asan_rtl.cc revision f03d8afc8b8dd072c4e2884a7475ee28ac5f3f41
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_mapping.h" 20#include "asan_stack.h" 21#include "asan_stats.h" 22#include "asan_thread.h" 23#include "asan_thread_registry.h" 24 25namespace __asan { 26 27// -------------------------- Flags ------------------------- {{{1 28static const size_t kMallocContextSize = 30; 29static int FLAG_atexit; 30 31size_t FLAG_redzone; // power of two, >= 32 32size_t FLAG_quarantine_size; 33int FLAG_demangle; 34bool FLAG_symbolize; 35int FLAG_v; 36int FLAG_debug; 37bool FLAG_poison_shadow; 38int FLAG_report_globals; 39size_t FLAG_malloc_context_size = kMallocContextSize; 40uintptr_t FLAG_large_malloc; 41bool FLAG_handle_segv; 42bool FLAG_use_sigaltstack; 43bool FLAG_replace_str; 44bool FLAG_replace_intrin; 45bool FLAG_replace_cfallocator; // Used on Mac only. 46size_t FLAG_max_malloc_fill_size = 0; 47bool FLAG_use_fake_stack; 48int FLAG_exitcode = ASAN_DEFAULT_FAILURE_EXITCODE; 49bool FLAG_allow_user_poisoning; 50int FLAG_sleep_before_dying; 51 52// -------------------------- Globals --------------------- {{{1 53int asan_inited; 54bool asan_init_is_running; 55static void (*death_callback)(void); 56static void (*error_report_callback)(const char*); 57char *error_message_buffer = NULL; 58size_t error_message_buffer_pos = 0; 59size_t error_message_buffer_size = 0; 60 61// -------------------------- Misc ---------------- {{{1 62void ShowStatsAndAbort() { 63 __asan_print_accumulated_stats(); 64 AsanDie(); 65} 66 67static void PrintBytes(const char *before, uintptr_t *a) { 68 uint8_t *bytes = (uint8_t*)a; 69 size_t byte_num = (__WORDSIZE) / 8; 70 Printf("%s%p:", before, (void*)a); 71 for (size_t i = 0; i < byte_num; i++) { 72 Printf(" %x%x", bytes[i] >> 4, bytes[i] & 15); 73 } 74 Printf("\n"); 75} 76 77size_t ReadFileToBuffer(const char *file_name, char **buff, 78 size_t *buff_size, size_t max_len) { 79 const size_t kMinFileLen = kPageSize; 80 size_t read_len = 0; 81 *buff = 0; 82 *buff_size = 0; 83 // The files we usually open are not seekable, so try different buffer sizes. 84 for (size_t size = kMinFileLen; size <= max_len; size *= 2) { 85 int fd = AsanOpenReadonly(file_name); 86 if (fd < 0) return -1; 87 AsanUnmapOrDie(*buff, *buff_size); 88 *buff = (char*)AsanMmapSomewhereOrDie(size, __FUNCTION__); 89 *buff_size = size; 90 // Read up to one page at a time. 91 read_len = 0; 92 bool reached_eof = false; 93 while (read_len + kPageSize <= size) { 94 size_t just_read = AsanRead(fd, *buff + read_len, kPageSize); 95 if (just_read == 0) { 96 reached_eof = true; 97 break; 98 } 99 read_len += just_read; 100 } 101 AsanClose(fd); 102 if (reached_eof) // We've read the whole file. 103 break; 104 } 105 return read_len; 106} 107 108void AsanDie() { 109 static int num_calls = 0; 110 if (AtomicInc(&num_calls) > 1) { 111 // Don't die twice - run a busy loop. 112 while (1) { } 113 } 114 if (FLAG_sleep_before_dying) { 115 Report("Sleeping for %d second(s)\n", FLAG_sleep_before_dying); 116 SleepForSeconds(FLAG_sleep_before_dying); 117 } 118 if (death_callback) 119 death_callback(); 120 Exit(FLAG_exitcode); 121} 122 123// ---------------------- mmap -------------------- {{{1 124void OutOfMemoryMessageAndDie(const char *mem_type, size_t size) { 125 Report("ERROR: AddressSanitizer failed to allocate " 126 "0x%zx (%zd) bytes of %s\n", 127 size, size, mem_type); 128 PRINT_CURRENT_STACK(); 129 ShowStatsAndAbort(); 130} 131 132// Reserve memory range [beg, end]. 133static void ReserveShadowMemoryRange(uintptr_t beg, uintptr_t end) { 134 CHECK((beg % kPageSize) == 0); 135 CHECK(((end + 1) % kPageSize) == 0); 136 size_t size = end - beg + 1; 137 void *res = AsanMmapFixedNoReserve(beg, size); 138 CHECK(res == (void*)beg && "ReserveShadowMemoryRange failed"); 139} 140 141// ---------------------- LowLevelAllocator ------------- {{{1 142void *LowLevelAllocator::Allocate(size_t size) { 143 CHECK((size & (size - 1)) == 0 && "size must be a power of two"); 144 if (allocated_end_ - allocated_current_ < size) { 145 size_t size_to_allocate = Max(size, kPageSize); 146 allocated_current_ = 147 (char*)AsanMmapSomewhereOrDie(size_to_allocate, __FUNCTION__); 148 allocated_end_ = allocated_current_ + size_to_allocate; 149 PoisonShadow((uintptr_t)allocated_current_, size_to_allocate, 150 kAsanInternalHeapMagic); 151 } 152 CHECK(allocated_end_ - allocated_current_ >= size); 153 void *res = allocated_current_; 154 allocated_current_ += size; 155 return res; 156} 157 158// ---------------------- DescribeAddress -------------------- {{{1 159static bool DescribeStackAddress(uintptr_t addr, uintptr_t access_size) { 160 AsanThread *t = asanThreadRegistry().FindThreadByStackAddress(addr); 161 if (!t) return false; 162 const intptr_t kBufSize = 4095; 163 char buf[kBufSize]; 164 uintptr_t offset = 0; 165 const char *frame_descr = t->GetFrameNameByAddr(addr, &offset); 166 // This string is created by the compiler and has the following form: 167 // "FunctioName n alloc_1 alloc_2 ... alloc_n" 168 // where alloc_i looks like "offset size len ObjectName ". 169 CHECK(frame_descr); 170 // Report the function name and the offset. 171 const char *name_end = internal_strchr(frame_descr, ' '); 172 CHECK(name_end); 173 buf[0] = 0; 174 internal_strncat(buf, frame_descr, 175 Min(kBufSize, 176 static_cast<intptr_t>(name_end - frame_descr))); 177 Printf("Address %p is located at offset %zu " 178 "in frame <%s> of T%d's stack:\n", 179 addr, offset, buf, t->tid()); 180 // Report the number of stack objects. 181 char *p; 182 size_t n_objects = internal_simple_strtoll(name_end, &p, 10); 183 CHECK(n_objects > 0); 184 Printf(" This frame has %zu object(s):\n", n_objects); 185 // Report all objects in this frame. 186 for (size_t i = 0; i < n_objects; i++) { 187 size_t beg, size; 188 intptr_t len; 189 beg = internal_simple_strtoll(p, &p, 10); 190 size = internal_simple_strtoll(p, &p, 10); 191 len = internal_simple_strtoll(p, &p, 10); 192 if (beg <= 0 || size <= 0 || len < 0 || *p != ' ') { 193 Printf("AddressSanitizer can't parse the stack frame descriptor: |%s|\n", 194 frame_descr); 195 break; 196 } 197 p++; 198 buf[0] = 0; 199 internal_strncat(buf, p, Min(kBufSize, len)); 200 p += len; 201 Printf(" [%zu, %zu) '%s'\n", beg, beg + size, buf); 202 } 203 Printf("HINT: this may be a false positive if your program uses " 204 "some custom stack unwind mechanism\n" 205 " (longjmp and C++ exceptions *are* supported)\n"); 206 t->summary()->Announce(); 207 return true; 208} 209 210static NOINLINE 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) \ 225NOINLINE ASAN_INTERFACE_ATTRIBUTE \ 226extern "C" void __asan_report_ ## type ## size(uintptr_t addr); \ 227extern "C" void __asan_report_ ## type ## size(uintptr_t addr) { \ 228 GET_CALLER_PC_BP_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 NOINLINE void force_interface_symbols() { 249 volatile int fake_condition = 0; // prevent dead condition elimination. 250 if (fake_condition) { 251 __asan_report_load1(0); 252 __asan_report_load2(0); 253 __asan_report_load4(0); 254 __asan_report_load8(0); 255 __asan_report_load16(0); 256 __asan_report_store1(0); 257 __asan_report_store2(0); 258 __asan_report_store4(0); 259 __asan_report_store8(0); 260 __asan_report_store16(0); 261 __asan_register_global(0, 0, NULL); 262 __asan_register_globals(NULL, 0); 263 __asan_unregister_globals(NULL, 0); 264 __asan_set_death_callback(NULL); 265 __asan_set_error_report_callback(NULL); 266 __asan_handle_no_return(); 267 } 268} 269 270// -------------------------- Init ------------------- {{{1 271static int64_t IntFlagValue(const char *flags, const char *flag, 272 int64_t default_val) { 273 if (!flags) return default_val; 274 const char *str = internal_strstr(flags, flag); 275 if (!str) return default_val; 276 return internal_atoll(str + internal_strlen(flag)); 277} 278 279static void asan_atexit() { 280 Printf("AddressSanitizer exit stats:\n"); 281 __asan_print_accumulated_stats(); 282} 283 284void CheckFailed(const char *cond, const char *file, int line) { 285 Report("CHECK failed: %s at %s:%d\n", cond, file, line); 286 PRINT_CURRENT_STACK(); 287 ShowStatsAndAbort(); 288} 289 290} // namespace __asan 291 292// ---------------------- Interface ---------------- {{{1 293using namespace __asan; // NOLINT 294 295int __asan_set_error_exit_code(int exit_code) { 296 int old = FLAG_exitcode; 297 FLAG_exitcode = exit_code; 298 return old; 299} 300 301void NOINLINE __asan_handle_no_return() { 302 int local_stack; 303 AsanThread *curr_thread = asanThreadRegistry().GetCurrent(); 304 CHECK(curr_thread); 305 uintptr_t top = curr_thread->stack_top(); 306 uintptr_t bottom = ((uintptr_t)&local_stack - kPageSize) & ~(kPageSize-1); 307 PoisonShadow(bottom, top - bottom, 0); 308} 309 310void NOINLINE __asan_set_death_callback(void (*callback)(void)) { 311 death_callback = callback; 312} 313 314void NOINLINE __asan_set_error_report_callback(void (*callback)(const char*)) { 315 error_report_callback = callback; 316 if (callback) { 317 error_message_buffer_size = 1 << 14; 318 error_message_buffer = 319 (char*)AsanMmapSomewhereOrDie(error_message_buffer_size, __FUNCTION__); 320 error_message_buffer_pos = 0; 321 } 322} 323 324void __asan_report_error(uintptr_t pc, uintptr_t bp, uintptr_t sp, 325 uintptr_t addr, bool is_write, size_t access_size) { 326 // Do not print more than one report, otherwise they will mix up. 327 static int num_calls = 0; 328 if (AtomicInc(&num_calls) > 1) return; 329 330 Printf("=================================================================\n"); 331 const char *bug_descr = "unknown-crash"; 332 if (AddrIsInMem(addr)) { 333 uint8_t *shadow_addr = (uint8_t*)MemToShadow(addr); 334 // If we are accessing 16 bytes, look at the second shadow byte. 335 if (*shadow_addr == 0 && access_size > SHADOW_GRANULARITY) 336 shadow_addr++; 337 // If we are in the partial right redzone, look at the next shadow byte. 338 if (*shadow_addr > 0 && *shadow_addr < 128) 339 shadow_addr++; 340 switch (*shadow_addr) { 341 case kAsanHeapLeftRedzoneMagic: 342 case kAsanHeapRightRedzoneMagic: 343 bug_descr = "heap-buffer-overflow"; 344 break; 345 case kAsanHeapFreeMagic: 346 bug_descr = "heap-use-after-free"; 347 break; 348 case kAsanStackLeftRedzoneMagic: 349 bug_descr = "stack-buffer-underflow"; 350 break; 351 case kAsanStackMidRedzoneMagic: 352 case kAsanStackRightRedzoneMagic: 353 case kAsanStackPartialRedzoneMagic: 354 bug_descr = "stack-buffer-overflow"; 355 break; 356 case kAsanStackAfterReturnMagic: 357 bug_descr = "stack-use-after-return"; 358 break; 359 case kAsanUserPoisonedMemoryMagic: 360 bug_descr = "use-after-poison"; 361 break; 362 case kAsanGlobalRedzoneMagic: 363 bug_descr = "global-buffer-overflow"; 364 break; 365 } 366 } 367 368 AsanThread *curr_thread = asanThreadRegistry().GetCurrent(); 369 int curr_tid = asanThreadRegistry().GetCurrentTidOrMinusOne(); 370 371 if (curr_thread) { 372 // We started reporting an error message. Stop using the fake stack 373 // in case we will call an instrumented function from a symbolizer. 374 curr_thread->fake_stack().StopUsingFakeStack(); 375 } 376 377 Report("ERROR: AddressSanitizer %s on address " 378 "%p at pc 0x%zx bp 0x%zx sp 0x%zx\n", 379 bug_descr, addr, pc, bp, sp); 380 381 Printf("%s of size %zu at %p thread T%d\n", 382 access_size ? (is_write ? "WRITE" : "READ") : "ACCESS", 383 access_size, addr, curr_tid); 384 385 if (FLAG_debug) { 386 PrintBytes("PC: ", (uintptr_t*)pc); 387 } 388 389 GET_STACK_TRACE_WITH_PC_AND_BP(kStackTraceMax, pc, bp); 390 stack.PrintStack(); 391 392 CHECK(AddrIsInMem(addr)); 393 394 DescribeAddress(addr, access_size); 395 396 uintptr_t shadow_addr = MemToShadow(addr); 397 Report("ABORTING\n"); 398 __asan_print_accumulated_stats(); 399 Printf("Shadow byte and word:\n"); 400 Printf(" %p: %x\n", shadow_addr, *(unsigned char*)shadow_addr); 401 uintptr_t aligned_shadow = shadow_addr & ~(kWordSize - 1); 402 PrintBytes(" ", (uintptr_t*)(aligned_shadow)); 403 Printf("More shadow bytes:\n"); 404 PrintBytes(" ", (uintptr_t*)(aligned_shadow-4*kWordSize)); 405 PrintBytes(" ", (uintptr_t*)(aligned_shadow-3*kWordSize)); 406 PrintBytes(" ", (uintptr_t*)(aligned_shadow-2*kWordSize)); 407 PrintBytes(" ", (uintptr_t*)(aligned_shadow-1*kWordSize)); 408 PrintBytes("=>", (uintptr_t*)(aligned_shadow+0*kWordSize)); 409 PrintBytes(" ", (uintptr_t*)(aligned_shadow+1*kWordSize)); 410 PrintBytes(" ", (uintptr_t*)(aligned_shadow+2*kWordSize)); 411 PrintBytes(" ", (uintptr_t*)(aligned_shadow+3*kWordSize)); 412 PrintBytes(" ", (uintptr_t*)(aligned_shadow+4*kWordSize)); 413 if (error_report_callback) { 414 error_report_callback(error_message_buffer); 415 } 416 AsanDie(); 417} 418 419void __asan_init() { 420 if (asan_inited) return; 421 asan_init_is_running = true; 422 423 // Make sure we are not statically linked. 424 AsanDoesNotSupportStaticLinkage(); 425 426 // flags 427 const char *options = AsanGetEnv("ASAN_OPTIONS"); 428 FLAG_malloc_context_size = 429 IntFlagValue(options, "malloc_context_size=", kMallocContextSize); 430 CHECK(FLAG_malloc_context_size <= kMallocContextSize); 431 432 FLAG_max_malloc_fill_size = 433 IntFlagValue(options, "max_malloc_fill_size=", 0); 434 435 FLAG_v = IntFlagValue(options, "verbosity=", 0); 436 437 FLAG_redzone = IntFlagValue(options, "redzone=", 438 (ASAN_LOW_MEMORY) ? 64 : 128); 439 CHECK(FLAG_redzone >= 32); 440 CHECK((FLAG_redzone & (FLAG_redzone - 1)) == 0); 441 442 FLAG_atexit = IntFlagValue(options, "atexit=", 0); 443 FLAG_poison_shadow = IntFlagValue(options, "poison_shadow=", 1); 444 FLAG_report_globals = IntFlagValue(options, "report_globals=", 1); 445 FLAG_handle_segv = IntFlagValue(options, "handle_segv=", ASAN_NEEDS_SEGV); 446 FLAG_use_sigaltstack = IntFlagValue(options, "use_sigaltstack=", 0); 447 FLAG_symbolize = IntFlagValue(options, "symbolize=", 1); 448 FLAG_demangle = IntFlagValue(options, "demangle=", 1); 449 FLAG_debug = IntFlagValue(options, "debug=", 0); 450 FLAG_replace_cfallocator = IntFlagValue(options, "replace_cfallocator=", 1); 451 FLAG_replace_str = IntFlagValue(options, "replace_str=", 1); 452 FLAG_replace_intrin = IntFlagValue(options, "replace_intrin=", 1); 453 FLAG_use_fake_stack = IntFlagValue(options, "use_fake_stack=", 1); 454 FLAG_exitcode = IntFlagValue(options, "exitcode=", 455 ASAN_DEFAULT_FAILURE_EXITCODE); 456 FLAG_allow_user_poisoning = IntFlagValue(options, 457 "allow_user_poisoning=", 1); 458 FLAG_sleep_before_dying = IntFlagValue(options, "sleep_before_dying=", 0); 459 460 FLAG_quarantine_size = IntFlagValue(options, "quarantine_size=", 461 (ASAN_LOW_MEMORY) ? 1UL << 24 : 1UL << 28); 462 463 if (FLAG_v) { 464 Report("Parsed ASAN_OPTIONS: %s\n", options); 465 } 466 467 if (FLAG_atexit) { 468 Atexit(asan_atexit); 469 } 470 471 // interceptors 472 InitializeAsanInterceptors(); 473 474 ReplaceSystemMalloc(); 475 476 if (FLAG_v) { 477 Printf("|| `[%p, %p]` || HighMem ||\n", kHighMemBeg, kHighMemEnd); 478 Printf("|| `[%p, %p]` || HighShadow ||\n", 479 kHighShadowBeg, kHighShadowEnd); 480 Printf("|| `[%p, %p]` || ShadowGap ||\n", 481 kShadowGapBeg, kShadowGapEnd); 482 Printf("|| `[%p, %p]` || LowShadow ||\n", 483 kLowShadowBeg, kLowShadowEnd); 484 Printf("|| `[%p, %p]` || LowMem ||\n", kLowMemBeg, kLowMemEnd); 485 Printf("MemToShadow(shadow): %p %p %p %p\n", 486 MEM_TO_SHADOW(kLowShadowBeg), 487 MEM_TO_SHADOW(kLowShadowEnd), 488 MEM_TO_SHADOW(kHighShadowBeg), 489 MEM_TO_SHADOW(kHighShadowEnd)); 490 Printf("red_zone=%zu\n", (size_t)FLAG_redzone); 491 Printf("malloc_context_size=%zu\n", (size_t)FLAG_malloc_context_size); 492 493 Printf("SHADOW_SCALE: %zx\n", (size_t)SHADOW_SCALE); 494 Printf("SHADOW_GRANULARITY: %zx\n", (size_t)SHADOW_GRANULARITY); 495 Printf("SHADOW_OFFSET: %zx\n", (size_t)SHADOW_OFFSET); 496 CHECK(SHADOW_SCALE >= 3 && SHADOW_SCALE <= 7); 497 } 498 499 if (__WORDSIZE == 64) { 500 // Disable core dumper -- it makes little sense to dump 16T+ core. 501 AsanDisableCoreDumper(); 502 } 503 504 if (AsanShadowRangeIsAvailable()) { 505 if (kLowShadowBeg != kLowShadowEnd) { 506 // mmap the low shadow plus at least one page. 507 ReserveShadowMemoryRange(kLowShadowBeg - kMmapGranularity, kLowShadowEnd); 508 } 509 // mmap the high shadow. 510 ReserveShadowMemoryRange(kHighShadowBeg, kHighShadowEnd); 511 // protect the gap 512 void *prot = AsanMprotect(kShadowGapBeg, kShadowGapEnd - kShadowGapBeg + 1); 513 CHECK(prot == (void*)kShadowGapBeg); 514 } else { 515 Report("Shadow memory range interleaves with an existing memory mapping. " 516 "ASan cannot proceed correctly. ABORTING.\n"); 517 AsanDumpProcessMap(); 518 AsanDie(); 519 } 520 521 InstallSignalHandlers(); 522 523 // On Linux AsanThread::ThreadStart() calls malloc() that's why asan_inited 524 // should be set to 1 prior to initializing the threads. 525 asan_inited = 1; 526 asan_init_is_running = false; 527 528 asanThreadRegistry().Init(); 529 asanThreadRegistry().GetMain()->ThreadStart(); 530 force_interface_symbols(); // no-op. 531 532 if (FLAG_v) { 533 Report("AddressSanitizer Init done\n"); 534 } 535} 536 537#if defined(ASAN_USE_PREINIT_ARRAY) 538 // On Linux, we force __asan_init to be called before anyone else 539 // by placing it into .preinit_array section. 540 // FIXME: do we have anything like this on Mac? 541 __attribute__((section(".preinit_array"))) 542 typeof(__asan_init) *__asan_preinit =__asan_init; 543#elif defined(_WIN32) && defined(_DLL) 544 // On Windows, when using dynamic CRT (/MD), we can put a pointer 545 // to __asan_init into the global list of C initializers. 546 // See crt0dat.c in the CRT sources for the details. 547 #pragma section(".CRT$XIB", long, read) // NOLINT 548 __declspec(allocate(".CRT$XIB")) void (*__asan_preinit)() = __asan_init; 549#endif 550