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