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