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