asan_interceptors.cc revision 3fa122e6a8e12db6583793861f6cf776fe1c98a0
1//===-- asan_interceptors.cc ----------------------------------------------===// 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// Intercept various libc functions. 13//===----------------------------------------------------------------------===// 14#include "asan_interceptors.h" 15 16#include "asan_allocator.h" 17#include "asan_intercepted_functions.h" 18#include "asan_internal.h" 19#include "asan_mapping.h" 20#include "asan_poisoning.h" 21#include "asan_report.h" 22#include "asan_stack.h" 23#include "asan_stats.h" 24#include "interception/interception.h" 25#include "sanitizer_common/sanitizer_libc.h" 26 27namespace __asan { 28 29// Return true if we can quickly decide that the region is unpoisoned. 30static inline bool QuickCheckForUnpoisonedRegion(uptr beg, uptr size) { 31 if (size == 0) return true; 32 if (size <= 32) 33 return !AddressIsPoisoned(beg) && 34 !AddressIsPoisoned(beg + size - 1) && 35 !AddressIsPoisoned(beg + size / 2); 36 return false; 37} 38 39// We implement ACCESS_MEMORY_RANGE, ASAN_READ_RANGE, 40// and ASAN_WRITE_RANGE as macro instead of function so 41// that no extra frames are created, and stack trace contains 42// relevant information only. 43// We check all shadow bytes. 44#define ACCESS_MEMORY_RANGE(offset, size, isWrite) do { \ 45 uptr __offset = (uptr)(offset); \ 46 uptr __size = (uptr)(size); \ 47 uptr __bad = 0; \ 48 if (!QuickCheckForUnpoisonedRegion(__offset, __size) && \ 49 (__bad = __asan_region_is_poisoned(__offset, __size))) { \ 50 GET_CURRENT_PC_BP_SP; \ 51 __asan_report_error(pc, bp, sp, __bad, isWrite, __size); \ 52 } \ 53 } while (0) 54 55#define ASAN_READ_RANGE(offset, size) ACCESS_MEMORY_RANGE(offset, size, false) 56#define ASAN_WRITE_RANGE(offset, size) ACCESS_MEMORY_RANGE(offset, size, true) 57 58// Behavior of functions like "memcpy" or "strcpy" is undefined 59// if memory intervals overlap. We report error in this case. 60// Macro is used to avoid creation of new frames. 61static inline bool RangesOverlap(const char *offset1, uptr length1, 62 const char *offset2, uptr length2) { 63 return !((offset1 + length1 <= offset2) || (offset2 + length2 <= offset1)); 64} 65#define CHECK_RANGES_OVERLAP(name, _offset1, length1, _offset2, length2) do { \ 66 const char *offset1 = (const char*)_offset1; \ 67 const char *offset2 = (const char*)_offset2; \ 68 if (RangesOverlap(offset1, length1, offset2, length2)) { \ 69 GET_STACK_TRACE_FATAL_HERE; \ 70 ReportStringFunctionMemoryRangesOverlap(name, offset1, length1, \ 71 offset2, length2, &stack); \ 72 } \ 73} while (0) 74 75#define ENSURE_ASAN_INITED() do { \ 76 CHECK(!asan_init_is_running); \ 77 if (!asan_inited) { \ 78 __asan_init(); \ 79 } \ 80} while (0) 81 82static inline uptr MaybeRealStrnlen(const char *s, uptr maxlen) { 83#if ASAN_INTERCEPT_STRNLEN 84 if (REAL(strnlen) != 0) { 85 return REAL(strnlen)(s, maxlen); 86 } 87#endif 88 return internal_strnlen(s, maxlen); 89} 90 91void SetThreadName(const char *name) { 92 AsanThread *t = GetCurrentThread(); 93 if (t) 94 asanThreadRegistry().SetThreadName(t->tid(), name); 95} 96 97} // namespace __asan 98 99// ---------------------- Wrappers ---------------- {{{1 100using namespace __asan; // NOLINT 101 102DECLARE_REAL_AND_INTERCEPTOR(void *, malloc, uptr) 103DECLARE_REAL_AND_INTERCEPTOR(void, free, void *) 104 105#define COMMON_INTERCEPTOR_UNPOISON_PARAM(ctx, count) \ 106 do { \ 107 } while (false) 108#define COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, size) \ 109 ASAN_WRITE_RANGE(ptr, size) 110#define COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, size) ASAN_READ_RANGE(ptr, size) 111#define COMMON_INTERCEPTOR_ENTER(ctx, func, ...) \ 112 do { \ 113 if (asan_init_is_running) return REAL(func)(__VA_ARGS__); \ 114 ctx = 0; \ 115 (void) ctx; \ 116 ENSURE_ASAN_INITED(); \ 117 } while (false) 118#define COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd) \ 119 do { \ 120 } while (false) 121#define COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd) \ 122 do { \ 123 } while (false) 124#define COMMON_INTERCEPTOR_FD_SOCKET_ACCEPT(ctx, fd, newfd) \ 125 do { \ 126 } while (false) 127#define COMMON_INTERCEPTOR_SET_THREAD_NAME(ctx, name) SetThreadName(name) 128#include "sanitizer_common/sanitizer_common_interceptors.inc" 129 130#define COMMON_SYSCALL_PRE_READ_RANGE(p, s) ASAN_READ_RANGE(p, s) 131#define COMMON_SYSCALL_PRE_WRITE_RANGE(p, s) ASAN_WRITE_RANGE(p, s) 132#define COMMON_SYSCALL_POST_READ_RANGE(p, s) \ 133 do { \ 134 } while (false) 135#define COMMON_SYSCALL_POST_WRITE_RANGE(p, s) \ 136 do { \ 137 } while (false) 138#include "sanitizer_common/sanitizer_common_syscalls.inc" 139 140static thread_return_t THREAD_CALLING_CONV asan_thread_start(void *arg) { 141 AsanThread *t = (AsanThread*)arg; 142 SetCurrentThread(t); 143 return t->ThreadStart(GetTid()); 144} 145 146#if ASAN_INTERCEPT_PTHREAD_CREATE 147extern "C" int pthread_attr_getdetachstate(void *attr, int *v); 148 149INTERCEPTOR(int, pthread_create, void *thread, 150 void *attr, void *(*start_routine)(void*), void *arg) { 151 EnsureMainThreadIDIsCorrect(); 152 // Strict init-order checking in thread-hostile. 153 if (flags()->strict_init_order) 154 StopInitOrderChecking(); 155 GET_STACK_TRACE_THREAD; 156 int detached = 0; 157 if (attr != 0) 158 pthread_attr_getdetachstate(attr, &detached); 159 160 u32 current_tid = GetCurrentTidOrInvalid(); 161 AsanThread *t = AsanThread::Create(start_routine, arg); 162 CreateThreadContextArgs args = { t, &stack }; 163 asanThreadRegistry().CreateThread(*(uptr*)t, detached, current_tid, &args); 164 return REAL(pthread_create)(thread, attr, asan_thread_start, t); 165} 166#endif // ASAN_INTERCEPT_PTHREAD_CREATE 167 168#if ASAN_INTERCEPT_SIGNAL_AND_SIGACTION 169INTERCEPTOR(void*, signal, int signum, void *handler) { 170 if (!AsanInterceptsSignal(signum) || flags()->allow_user_segv_handler) { 171 return REAL(signal)(signum, handler); 172 } 173 return 0; 174} 175 176INTERCEPTOR(int, sigaction, int signum, const struct sigaction *act, 177 struct sigaction *oldact) { 178 if (!AsanInterceptsSignal(signum) || flags()->allow_user_segv_handler) { 179 return REAL(sigaction)(signum, act, oldact); 180 } 181 return 0; 182} 183#elif SANITIZER_POSIX 184// We need to have defined REAL(sigaction) on posix systems. 185DEFINE_REAL(int, sigaction, int signum, const struct sigaction *act, 186 struct sigaction *oldact) 187#endif // ASAN_INTERCEPT_SIGNAL_AND_SIGACTION 188 189#if ASAN_INTERCEPT_SWAPCONTEXT 190static void ClearShadowMemoryForContextStack(uptr stack, uptr ssize) { 191 // Align to page size. 192 uptr PageSize = GetPageSizeCached(); 193 uptr bottom = stack & ~(PageSize - 1); 194 ssize += stack - bottom; 195 ssize = RoundUpTo(ssize, PageSize); 196 static const uptr kMaxSaneContextStackSize = 1 << 22; // 4 Mb 197 if (ssize && ssize <= kMaxSaneContextStackSize) { 198 PoisonShadow(bottom, ssize, 0); 199 } 200} 201 202INTERCEPTOR(int, swapcontext, struct ucontext_t *oucp, 203 struct ucontext_t *ucp) { 204 static bool reported_warning = false; 205 if (!reported_warning) { 206 Report("WARNING: ASan doesn't fully support makecontext/swapcontext " 207 "functions and may produce false positives in some cases!\n"); 208 reported_warning = true; 209 } 210 // Clear shadow memory for new context (it may share stack 211 // with current context). 212 uptr stack, ssize; 213 ReadContextStack(ucp, &stack, &ssize); 214 ClearShadowMemoryForContextStack(stack, ssize); 215 int res = REAL(swapcontext)(oucp, ucp); 216 // swapcontext technically does not return, but program may swap context to 217 // "oucp" later, that would look as if swapcontext() returned 0. 218 // We need to clear shadow for ucp once again, as it may be in arbitrary 219 // state. 220 ClearShadowMemoryForContextStack(stack, ssize); 221 return res; 222} 223#endif // ASAN_INTERCEPT_SWAPCONTEXT 224 225INTERCEPTOR(void, longjmp, void *env, int val) { 226 __asan_handle_no_return(); 227 REAL(longjmp)(env, val); 228} 229 230#if ASAN_INTERCEPT__LONGJMP 231INTERCEPTOR(void, _longjmp, void *env, int val) { 232 __asan_handle_no_return(); 233 REAL(_longjmp)(env, val); 234} 235#endif 236 237#if ASAN_INTERCEPT_SIGLONGJMP 238INTERCEPTOR(void, siglongjmp, void *env, int val) { 239 __asan_handle_no_return(); 240 REAL(siglongjmp)(env, val); 241} 242#endif 243 244#if ASAN_INTERCEPT___CXA_THROW 245INTERCEPTOR(void, __cxa_throw, void *a, void *b, void *c) { 246 CHECK(REAL(__cxa_throw)); 247 __asan_handle_no_return(); 248 REAL(__cxa_throw)(a, b, c); 249} 250#endif 251 252// intercept mlock and friends. 253// Since asan maps 16T of RAM, mlock is completely unfriendly to asan. 254// All functions return 0 (success). 255static void MlockIsUnsupported() { 256 static bool printed = false; 257 if (printed) return; 258 printed = true; 259 if (flags()->verbosity > 0) 260 Printf("INFO: AddressSanitizer ignores mlock/mlockall/munlock/munlockall\n"); 261} 262 263INTERCEPTOR(int, mlock, const void *addr, uptr len) { 264 MlockIsUnsupported(); 265 return 0; 266} 267 268INTERCEPTOR(int, munlock, const void *addr, uptr len) { 269 MlockIsUnsupported(); 270 return 0; 271} 272 273INTERCEPTOR(int, mlockall, int flags) { 274 MlockIsUnsupported(); 275 return 0; 276} 277 278INTERCEPTOR(int, munlockall, void) { 279 MlockIsUnsupported(); 280 return 0; 281} 282 283static inline int CharCmp(unsigned char c1, unsigned char c2) { 284 return (c1 == c2) ? 0 : (c1 < c2) ? -1 : 1; 285} 286 287INTERCEPTOR(int, memcmp, const void *a1, const void *a2, uptr size) { 288 if (!asan_inited) return internal_memcmp(a1, a2, size); 289 ENSURE_ASAN_INITED(); 290 if (flags()->replace_intrin) { 291 if (flags()->strict_memcmp) { 292 // Check the entire regions even if the first bytes of the buffers are 293 // different. 294 ASAN_READ_RANGE(a1, size); 295 ASAN_READ_RANGE(a2, size); 296 // Fallthrough to REAL(memcmp) below. 297 } else { 298 unsigned char c1 = 0, c2 = 0; 299 const unsigned char *s1 = (const unsigned char*)a1; 300 const unsigned char *s2 = (const unsigned char*)a2; 301 uptr i; 302 for (i = 0; i < size; i++) { 303 c1 = s1[i]; 304 c2 = s2[i]; 305 if (c1 != c2) break; 306 } 307 ASAN_READ_RANGE(s1, Min(i + 1, size)); 308 ASAN_READ_RANGE(s2, Min(i + 1, size)); 309 return CharCmp(c1, c2); 310 } 311 } 312 return REAL(memcmp(a1, a2, size)); 313} 314 315INTERCEPTOR(void*, memcpy, void *to, const void *from, uptr size) { 316 if (!asan_inited) return internal_memcpy(to, from, size); 317 // memcpy is called during __asan_init() from the internals 318 // of printf(...). 319 if (asan_init_is_running) { 320 return REAL(memcpy)(to, from, size); 321 } 322 ENSURE_ASAN_INITED(); 323 if (flags()->replace_intrin) { 324 if (to != from) { 325 // We do not treat memcpy with to==from as a bug. 326 // See http://llvm.org/bugs/show_bug.cgi?id=11763. 327 CHECK_RANGES_OVERLAP("memcpy", to, size, from, size); 328 } 329 ASAN_READ_RANGE(from, size); 330 ASAN_WRITE_RANGE(to, size); 331 } 332 // Interposing of resolver functions is broken on Mac OS 10.7 and 10.8. 333 // See also http://code.google.com/p/address-sanitizer/issues/detail?id=116. 334 return internal_memcpy(to, from, size); 335} 336 337INTERCEPTOR(void*, memmove, void *to, const void *from, uptr size) { 338 if (!asan_inited) return internal_memmove(to, from, size); 339 if (asan_init_is_running) { 340 return REAL(memmove)(to, from, size); 341 } 342 ENSURE_ASAN_INITED(); 343 if (flags()->replace_intrin) { 344 ASAN_READ_RANGE(from, size); 345 ASAN_WRITE_RANGE(to, size); 346 } 347 // Interposing of resolver functions is broken on Mac OS 10.7 and 10.8. 348 // See also http://code.google.com/p/address-sanitizer/issues/detail?id=116. 349 return internal_memmove(to, from, size); 350} 351 352INTERCEPTOR(void*, memset, void *block, int c, uptr size) { 353 if (!asan_inited) return internal_memset(block, c, size); 354 // memset is called inside Printf. 355 if (asan_init_is_running) { 356 return REAL(memset)(block, c, size); 357 } 358 ENSURE_ASAN_INITED(); 359 if (flags()->replace_intrin) { 360 ASAN_WRITE_RANGE(block, size); 361 } 362 return REAL(memset)(block, c, size); 363} 364 365INTERCEPTOR(char*, strchr, const char *str, int c) { 366 if (!asan_inited) return internal_strchr(str, c); 367 // strchr is called inside create_purgeable_zone() when MallocGuardEdges=1 is 368 // used. 369 if (asan_init_is_running) { 370 return REAL(strchr)(str, c); 371 } 372 ENSURE_ASAN_INITED(); 373 char *result = REAL(strchr)(str, c); 374 if (flags()->replace_str) { 375 uptr bytes_read = (result ? result - str : REAL(strlen)(str)) + 1; 376 ASAN_READ_RANGE(str, bytes_read); 377 } 378 return result; 379} 380 381#if ASAN_INTERCEPT_INDEX 382# if ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX 383INTERCEPTOR(char*, index, const char *string, int c) 384 ALIAS(WRAPPER_NAME(strchr)); 385# else 386# if SANITIZER_MAC 387DECLARE_REAL(char*, index, const char *string, int c) 388OVERRIDE_FUNCTION(index, strchr); 389# else 390DEFINE_REAL(char*, index, const char *string, int c) 391# endif 392# endif 393#endif // ASAN_INTERCEPT_INDEX 394 395// For both strcat() and strncat() we need to check the validity of |to| 396// argument irrespective of the |from| length. 397INTERCEPTOR(char*, strcat, char *to, const char *from) { // NOLINT 398 ENSURE_ASAN_INITED(); 399 if (flags()->replace_str) { 400 uptr from_length = REAL(strlen)(from); 401 ASAN_READ_RANGE(from, from_length + 1); 402 uptr to_length = REAL(strlen)(to); 403 ASAN_READ_RANGE(to, to_length); 404 ASAN_WRITE_RANGE(to + to_length, from_length + 1); 405 // If the copying actually happens, the |from| string should not overlap 406 // with the resulting string starting at |to|, which has a length of 407 // to_length + from_length + 1. 408 if (from_length > 0) { 409 CHECK_RANGES_OVERLAP("strcat", to, from_length + to_length + 1, 410 from, from_length + 1); 411 } 412 } 413 return REAL(strcat)(to, from); // NOLINT 414} 415 416INTERCEPTOR(char*, strncat, char *to, const char *from, uptr size) { 417 ENSURE_ASAN_INITED(); 418 if (flags()->replace_str) { 419 uptr from_length = MaybeRealStrnlen(from, size); 420 uptr copy_length = Min(size, from_length + 1); 421 ASAN_READ_RANGE(from, copy_length); 422 uptr to_length = REAL(strlen)(to); 423 ASAN_READ_RANGE(to, to_length); 424 ASAN_WRITE_RANGE(to + to_length, from_length + 1); 425 if (from_length > 0) { 426 CHECK_RANGES_OVERLAP("strncat", to, to_length + copy_length + 1, 427 from, copy_length); 428 } 429 } 430 return REAL(strncat)(to, from, size); 431} 432 433INTERCEPTOR(int, strcmp, const char *s1, const char *s2) { 434 if (!asan_inited) return internal_strcmp(s1, s2); 435 if (asan_init_is_running) { 436 return REAL(strcmp)(s1, s2); 437 } 438 ENSURE_ASAN_INITED(); 439 unsigned char c1, c2; 440 uptr i; 441 for (i = 0; ; i++) { 442 c1 = (unsigned char)s1[i]; 443 c2 = (unsigned char)s2[i]; 444 if (c1 != c2 || c1 == '\0') break; 445 } 446 ASAN_READ_RANGE(s1, i + 1); 447 ASAN_READ_RANGE(s2, i + 1); 448 return CharCmp(c1, c2); 449} 450 451INTERCEPTOR(char*, strcpy, char *to, const char *from) { // NOLINT 452#if SANITIZER_MAC 453 if (!asan_inited) return REAL(strcpy)(to, from); // NOLINT 454#endif 455 // strcpy is called from malloc_default_purgeable_zone() 456 // in __asan::ReplaceSystemAlloc() on Mac. 457 if (asan_init_is_running) { 458 return REAL(strcpy)(to, from); // NOLINT 459 } 460 ENSURE_ASAN_INITED(); 461 if (flags()->replace_str) { 462 uptr from_size = REAL(strlen)(from) + 1; 463 CHECK_RANGES_OVERLAP("strcpy", to, from_size, from, from_size); 464 ASAN_READ_RANGE(from, from_size); 465 ASAN_WRITE_RANGE(to, from_size); 466 } 467 return REAL(strcpy)(to, from); // NOLINT 468} 469 470#if ASAN_INTERCEPT_STRDUP 471INTERCEPTOR(char*, strdup, const char *s) { 472 if (!asan_inited) return internal_strdup(s); 473 ENSURE_ASAN_INITED(); 474 uptr length = REAL(strlen)(s); 475 if (flags()->replace_str) { 476 ASAN_READ_RANGE(s, length + 1); 477 } 478 GET_STACK_TRACE_MALLOC; 479 void *new_mem = asan_malloc(length + 1, &stack); 480 REAL(memcpy)(new_mem, s, length + 1); 481 return reinterpret_cast<char*>(new_mem); 482} 483#endif 484 485INTERCEPTOR(uptr, strlen, const char *s) { 486 if (!asan_inited) return internal_strlen(s); 487 // strlen is called from malloc_default_purgeable_zone() 488 // in __asan::ReplaceSystemAlloc() on Mac. 489 if (asan_init_is_running) { 490 return REAL(strlen)(s); 491 } 492 ENSURE_ASAN_INITED(); 493 uptr length = REAL(strlen)(s); 494 if (flags()->replace_str) { 495 ASAN_READ_RANGE(s, length + 1); 496 } 497 return length; 498} 499 500INTERCEPTOR(int, strncmp, const char *s1, const char *s2, uptr size) { 501 if (!asan_inited) return internal_strncmp(s1, s2, size); 502 // strncmp is called from malloc_default_purgeable_zone() 503 // in __asan::ReplaceSystemAlloc() on Mac. 504 if (asan_init_is_running) { 505 return REAL(strncmp)(s1, s2, size); 506 } 507 ENSURE_ASAN_INITED(); 508 unsigned char c1 = 0, c2 = 0; 509 uptr i; 510 for (i = 0; i < size; i++) { 511 c1 = (unsigned char)s1[i]; 512 c2 = (unsigned char)s2[i]; 513 if (c1 != c2 || c1 == '\0') break; 514 } 515 ASAN_READ_RANGE(s1, Min(i + 1, size)); 516 ASAN_READ_RANGE(s2, Min(i + 1, size)); 517 return CharCmp(c1, c2); 518} 519 520INTERCEPTOR(char*, strncpy, char *to, const char *from, uptr size) { 521 ENSURE_ASAN_INITED(); 522 if (flags()->replace_str) { 523 uptr from_size = Min(size, MaybeRealStrnlen(from, size) + 1); 524 CHECK_RANGES_OVERLAP("strncpy", to, from_size, from, from_size); 525 ASAN_READ_RANGE(from, from_size); 526 ASAN_WRITE_RANGE(to, size); 527 } 528 return REAL(strncpy)(to, from, size); 529} 530 531#if ASAN_INTERCEPT_STRNLEN 532INTERCEPTOR(uptr, strnlen, const char *s, uptr maxlen) { 533 ENSURE_ASAN_INITED(); 534 uptr length = REAL(strnlen)(s, maxlen); 535 if (flags()->replace_str) { 536 ASAN_READ_RANGE(s, Min(length + 1, maxlen)); 537 } 538 return length; 539} 540#endif // ASAN_INTERCEPT_STRNLEN 541 542static inline bool IsValidStrtolBase(int base) { 543 return (base == 0) || (2 <= base && base <= 36); 544} 545 546static inline void FixRealStrtolEndptr(const char *nptr, char **endptr) { 547 CHECK(endptr); 548 if (nptr == *endptr) { 549 // No digits were found at strtol call, we need to find out the last 550 // symbol accessed by strtoll on our own. 551 // We get this symbol by skipping leading blanks and optional +/- sign. 552 while (IsSpace(*nptr)) nptr++; 553 if (*nptr == '+' || *nptr == '-') nptr++; 554 *endptr = (char*)nptr; 555 } 556 CHECK(*endptr >= nptr); 557} 558 559INTERCEPTOR(long, strtol, const char *nptr, // NOLINT 560 char **endptr, int base) { 561 ENSURE_ASAN_INITED(); 562 if (!flags()->replace_str) { 563 return REAL(strtol)(nptr, endptr, base); 564 } 565 char *real_endptr; 566 long result = REAL(strtol)(nptr, &real_endptr, base); // NOLINT 567 if (endptr != 0) { 568 *endptr = real_endptr; 569 } 570 if (IsValidStrtolBase(base)) { 571 FixRealStrtolEndptr(nptr, &real_endptr); 572 ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1); 573 } 574 return result; 575} 576 577INTERCEPTOR(int, atoi, const char *nptr) { 578#if SANITIZER_MAC 579 if (!asan_inited) return REAL(atoi)(nptr); 580#endif 581 ENSURE_ASAN_INITED(); 582 if (!flags()->replace_str) { 583 return REAL(atoi)(nptr); 584 } 585 char *real_endptr; 586 // "man atoi" tells that behavior of atoi(nptr) is the same as 587 // strtol(nptr, 0, 10), i.e. it sets errno to ERANGE if the 588 // parsed integer can't be stored in *long* type (even if it's 589 // different from int). So, we just imitate this behavior. 590 int result = REAL(strtol)(nptr, &real_endptr, 10); 591 FixRealStrtolEndptr(nptr, &real_endptr); 592 ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1); 593 return result; 594} 595 596INTERCEPTOR(long, atol, const char *nptr) { // NOLINT 597#if SANITIZER_MAC 598 if (!asan_inited) return REAL(atol)(nptr); 599#endif 600 ENSURE_ASAN_INITED(); 601 if (!flags()->replace_str) { 602 return REAL(atol)(nptr); 603 } 604 char *real_endptr; 605 long result = REAL(strtol)(nptr, &real_endptr, 10); // NOLINT 606 FixRealStrtolEndptr(nptr, &real_endptr); 607 ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1); 608 return result; 609} 610 611#if ASAN_INTERCEPT_ATOLL_AND_STRTOLL 612INTERCEPTOR(long long, strtoll, const char *nptr, // NOLINT 613 char **endptr, int base) { 614 ENSURE_ASAN_INITED(); 615 if (!flags()->replace_str) { 616 return REAL(strtoll)(nptr, endptr, base); 617 } 618 char *real_endptr; 619 long long result = REAL(strtoll)(nptr, &real_endptr, base); // NOLINT 620 if (endptr != 0) { 621 *endptr = real_endptr; 622 } 623 // If base has unsupported value, strtoll can exit with EINVAL 624 // without reading any characters. So do additional checks only 625 // if base is valid. 626 if (IsValidStrtolBase(base)) { 627 FixRealStrtolEndptr(nptr, &real_endptr); 628 ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1); 629 } 630 return result; 631} 632 633INTERCEPTOR(long long, atoll, const char *nptr) { // NOLINT 634 ENSURE_ASAN_INITED(); 635 if (!flags()->replace_str) { 636 return REAL(atoll)(nptr); 637 } 638 char *real_endptr; 639 long long result = REAL(strtoll)(nptr, &real_endptr, 10); // NOLINT 640 FixRealStrtolEndptr(nptr, &real_endptr); 641 ASAN_READ_RANGE(nptr, (real_endptr - nptr) + 1); 642 return result; 643} 644#endif // ASAN_INTERCEPT_ATOLL_AND_STRTOLL 645 646static void AtCxaAtexit(void *unused) { 647 (void)unused; 648 StopInitOrderChecking(); 649} 650 651#if ASAN_INTERCEPT___CXA_ATEXIT 652INTERCEPTOR(int, __cxa_atexit, void (*func)(void *), void *arg, 653 void *dso_handle) { 654 ENSURE_ASAN_INITED(); 655 int res = REAL(__cxa_atexit)(func, arg, dso_handle); 656 REAL(__cxa_atexit)(AtCxaAtexit, 0, 0); 657 return res; 658} 659#endif // ASAN_INTERCEPT___CXA_ATEXIT 660 661#if !SANITIZER_MAC 662#define ASAN_INTERCEPT_FUNC(name) do { \ 663 if (!INTERCEPT_FUNCTION(name) && flags()->verbosity > 0) \ 664 Report("AddressSanitizer: failed to intercept '" #name "'\n"); \ 665 } while (0) 666#else 667// OS X interceptors don't need to be initialized with INTERCEPT_FUNCTION. 668#define ASAN_INTERCEPT_FUNC(name) 669#endif // SANITIZER_MAC 670 671#if SANITIZER_WINDOWS 672INTERCEPTOR_WINAPI(DWORD, CreateThread, 673 void* security, uptr stack_size, 674 DWORD (__stdcall *start_routine)(void*), void* arg, 675 DWORD thr_flags, void* tid) { 676 // Strict init-order checking in thread-hostile. 677 if (flags()->strict_init_order) 678 StopInitOrderChecking(); 679 GET_STACK_TRACE_THREAD; 680 u32 current_tid = GetCurrentTidOrInvalid(); 681 AsanThread *t = AsanThread::Create(start_routine, arg); 682 CreateThreadContextArgs args = { t, &stack }; 683 bool detached = false; // FIXME: how can we determine it on Windows? 684 asanThreadRegistry().CreateThread(*(uptr*)t, detached, current_tid, &args); 685 return REAL(CreateThread)(security, stack_size, 686 asan_thread_start, t, thr_flags, tid); 687} 688 689namespace __asan { 690void InitializeWindowsInterceptors() { 691 ASAN_INTERCEPT_FUNC(CreateThread); 692} 693 694} // namespace __asan 695#endif 696 697// ---------------------- InitializeAsanInterceptors ---------------- {{{1 698namespace __asan { 699void InitializeAsanInterceptors() { 700 static bool was_called_once; 701 CHECK(was_called_once == false); 702 was_called_once = true; 703 SANITIZER_COMMON_INTERCEPTORS_INIT; 704 705 // Intercept mem* functions. 706 ASAN_INTERCEPT_FUNC(memcmp); 707 ASAN_INTERCEPT_FUNC(memmove); 708 ASAN_INTERCEPT_FUNC(memset); 709 if (PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE) { 710 ASAN_INTERCEPT_FUNC(memcpy); 711 } 712 713 // Intercept str* functions. 714 ASAN_INTERCEPT_FUNC(strcat); // NOLINT 715 ASAN_INTERCEPT_FUNC(strchr); 716 ASAN_INTERCEPT_FUNC(strcmp); 717 ASAN_INTERCEPT_FUNC(strcpy); // NOLINT 718 ASAN_INTERCEPT_FUNC(strlen); 719 ASAN_INTERCEPT_FUNC(strncat); 720 ASAN_INTERCEPT_FUNC(strncmp); 721 ASAN_INTERCEPT_FUNC(strncpy); 722#if ASAN_INTERCEPT_STRDUP 723 ASAN_INTERCEPT_FUNC(strdup); 724#endif 725#if ASAN_INTERCEPT_STRNLEN 726 ASAN_INTERCEPT_FUNC(strnlen); 727#endif 728#if ASAN_INTERCEPT_INDEX && ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX 729 ASAN_INTERCEPT_FUNC(index); 730#endif 731 732 ASAN_INTERCEPT_FUNC(atoi); 733 ASAN_INTERCEPT_FUNC(atol); 734 ASAN_INTERCEPT_FUNC(strtol); 735#if ASAN_INTERCEPT_ATOLL_AND_STRTOLL 736 ASAN_INTERCEPT_FUNC(atoll); 737 ASAN_INTERCEPT_FUNC(strtoll); 738#endif 739 740#if ASAN_INTERCEPT_MLOCKX 741 // Intercept mlock/munlock. 742 ASAN_INTERCEPT_FUNC(mlock); 743 ASAN_INTERCEPT_FUNC(munlock); 744 ASAN_INTERCEPT_FUNC(mlockall); 745 ASAN_INTERCEPT_FUNC(munlockall); 746#endif 747 748 // Intecept signal- and jump-related functions. 749 ASAN_INTERCEPT_FUNC(longjmp); 750#if ASAN_INTERCEPT_SIGNAL_AND_SIGACTION 751 ASAN_INTERCEPT_FUNC(sigaction); 752 ASAN_INTERCEPT_FUNC(signal); 753#endif 754#if ASAN_INTERCEPT_SWAPCONTEXT 755 ASAN_INTERCEPT_FUNC(swapcontext); 756#endif 757#if ASAN_INTERCEPT__LONGJMP 758 ASAN_INTERCEPT_FUNC(_longjmp); 759#endif 760#if ASAN_INTERCEPT_SIGLONGJMP 761 ASAN_INTERCEPT_FUNC(siglongjmp); 762#endif 763 764 // Intercept exception handling functions. 765#if ASAN_INTERCEPT___CXA_THROW 766 INTERCEPT_FUNCTION(__cxa_throw); 767#endif 768 769 // Intercept threading-related functions 770#if ASAN_INTERCEPT_PTHREAD_CREATE 771 ASAN_INTERCEPT_FUNC(pthread_create); 772#endif 773 774 // Intercept atexit function. 775#if ASAN_INTERCEPT___CXA_ATEXIT 776 ASAN_INTERCEPT_FUNC(__cxa_atexit); 777#endif 778 779 // Some Windows-specific interceptors. 780#if SANITIZER_WINDOWS 781 InitializeWindowsInterceptors(); 782#endif 783 784 if (flags()->verbosity > 0) { 785 Report("AddressSanitizer: libc interceptors initialized\n"); 786 } 787} 788 789} // namespace __asan 790