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