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