1 //===-- asan_interceptors.cpp ---------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file is a part of AddressSanitizer, an address sanity checker. 10 // 11 // Intercept various libc functions. 12 //===----------------------------------------------------------------------===// 13 14 #include "asan_interceptors.h" 15 #include "asan_allocator.h" 16 #include "asan_internal.h" 17 #include "asan_mapping.h" 18 #include "asan_poisoning.h" 19 #include "asan_report.h" 20 #include "asan_stack.h" 21 #include "asan_stats.h" 22 #include "asan_suppressions.h" 23 #include "lsan/lsan_common.h" 24 #include "sanitizer_common/sanitizer_libc.h" 25 26 // There is no general interception at all on Fuchsia. 27 // Only the functions in asan_interceptors_memintrinsics.cpp are 28 // really defined to replace libc functions. 29 #if !SANITIZER_FUCHSIA 30 31 # if SANITIZER_POSIX 32 # include "sanitizer_common/sanitizer_posix.h" 33 # endif 34 35 # if ASAN_INTERCEPT__UNWIND_RAISEEXCEPTION || \ 36 ASAN_INTERCEPT__SJLJ_UNWIND_RAISEEXCEPTION 37 # include <unwind.h> 38 # endif 39 40 # if defined(__i386) && SANITIZER_LINUX 41 # define ASAN_PTHREAD_CREATE_VERSION "GLIBC_2.1" 42 # elif defined(__mips__) && SANITIZER_LINUX 43 # define ASAN_PTHREAD_CREATE_VERSION "GLIBC_2.2" 44 # endif 45 46 namespace __asan { 47 48 #define ASAN_READ_STRING_OF_LEN(ctx, s, len, n) \ 49 ASAN_READ_RANGE((ctx), (s), \ 50 common_flags()->strict_string_checks ? (len) + 1 : (n)) 51 52 # define ASAN_READ_STRING(ctx, s, n) \ 53 ASAN_READ_STRING_OF_LEN((ctx), (s), internal_strlen(s), (n)) 54 55 static inline uptr MaybeRealStrnlen(const char *s, uptr maxlen) { 56 #if SANITIZER_INTERCEPT_STRNLEN 57 if (REAL(strnlen)) { 58 return REAL(strnlen)(s, maxlen); 59 } 60 #endif 61 return internal_strnlen(s, maxlen); 62 } 63 64 void SetThreadName(const char *name) { 65 AsanThread *t = GetCurrentThread(); 66 if (t) 67 asanThreadRegistry().SetThreadName(t->tid(), name); 68 } 69 70 int OnExit() { 71 if (CAN_SANITIZE_LEAKS && common_flags()->detect_leaks && 72 __lsan::HasReportedLeaks()) { 73 return common_flags()->exitcode; 74 } 75 // FIXME: ask frontend whether we need to return failure. 76 return 0; 77 } 78 79 } // namespace __asan 80 81 // ---------------------- Wrappers ---------------- {{{1 82 using namespace __asan; 83 84 DECLARE_REAL_AND_INTERCEPTOR(void *, malloc, uptr) 85 DECLARE_REAL_AND_INTERCEPTOR(void, free, void *) 86 87 #define ASAN_INTERCEPTOR_ENTER(ctx, func) \ 88 AsanInterceptorContext _ctx = {#func}; \ 89 ctx = (void *)&_ctx; \ 90 (void) ctx; \ 91 92 #define COMMON_INTERCEPT_FUNCTION(name) ASAN_INTERCEPT_FUNC(name) 93 #define COMMON_INTERCEPT_FUNCTION_VER(name, ver) \ 94 ASAN_INTERCEPT_FUNC_VER(name, ver) 95 #define COMMON_INTERCEPT_FUNCTION_VER_UNVERSIONED_FALLBACK(name, ver) \ 96 ASAN_INTERCEPT_FUNC_VER_UNVERSIONED_FALLBACK(name, ver) 97 #define COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, size) \ 98 ASAN_WRITE_RANGE(ctx, ptr, size) 99 #define COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, size) \ 100 ASAN_READ_RANGE(ctx, ptr, size) 101 #define COMMON_INTERCEPTOR_ENTER(ctx, func, ...) \ 102 ASAN_INTERCEPTOR_ENTER(ctx, func); \ 103 do { \ 104 if (asan_init_is_running) \ 105 return REAL(func)(__VA_ARGS__); \ 106 if (SANITIZER_APPLE && UNLIKELY(!asan_inited)) \ 107 return REAL(func)(__VA_ARGS__); \ 108 ENSURE_ASAN_INITED(); \ 109 } while (false) 110 #define COMMON_INTERCEPTOR_DIR_ACQUIRE(ctx, path) \ 111 do { \ 112 } while (false) 113 #define COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd) \ 114 do { \ 115 } while (false) 116 #define COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd) \ 117 do { \ 118 } while (false) 119 #define COMMON_INTERCEPTOR_FD_SOCKET_ACCEPT(ctx, fd, newfd) \ 120 do { \ 121 } while (false) 122 #define COMMON_INTERCEPTOR_SET_THREAD_NAME(ctx, name) SetThreadName(name) 123 // Should be asanThreadRegistry().SetThreadNameByUserId(thread, name) 124 // But asan does not remember UserId's for threads (pthread_t); 125 // and remembers all ever existed threads, so the linear search by UserId 126 // can be slow. 127 #define COMMON_INTERCEPTOR_SET_PTHREAD_NAME(ctx, thread, name) \ 128 do { \ 129 } while (false) 130 #define COMMON_INTERCEPTOR_BLOCK_REAL(name) REAL(name) 131 // Strict init-order checking is dlopen-hostile: 132 // https://github.com/google/sanitizers/issues/178 133 # define COMMON_INTERCEPTOR_DLOPEN(filename, flag) \ 134 ({ \ 135 if (flags()->strict_init_order) \ 136 StopInitOrderChecking(); \ 137 CheckNoDeepBind(filename, flag); \ 138 REAL(dlopen)(filename, flag); \ 139 }) 140 # define COMMON_INTERCEPTOR_ON_EXIT(ctx) OnExit() 141 # define COMMON_INTERCEPTOR_LIBRARY_LOADED(filename, handle) 142 # define COMMON_INTERCEPTOR_LIBRARY_UNLOADED() 143 # define COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED (!asan_inited) 144 # define COMMON_INTERCEPTOR_GET_TLS_RANGE(begin, end) \ 145 if (AsanThread *t = GetCurrentThread()) { \ 146 *begin = t->tls_begin(); \ 147 *end = t->tls_end(); \ 148 } else { \ 149 *begin = *end = 0; \ 150 } 151 152 #define COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, to, from, size) \ 153 do { \ 154 ASAN_INTERCEPTOR_ENTER(ctx, memmove); \ 155 ASAN_MEMMOVE_IMPL(ctx, to, from, size); \ 156 } while (false) 157 158 #define COMMON_INTERCEPTOR_MEMCPY_IMPL(ctx, to, from, size) \ 159 do { \ 160 ASAN_INTERCEPTOR_ENTER(ctx, memcpy); \ 161 ASAN_MEMCPY_IMPL(ctx, to, from, size); \ 162 } while (false) 163 164 #define COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, c, size) \ 165 do { \ 166 ASAN_INTERCEPTOR_ENTER(ctx, memset); \ 167 ASAN_MEMSET_IMPL(ctx, block, c, size); \ 168 } while (false) 169 170 #if CAN_SANITIZE_LEAKS 171 #define COMMON_INTERCEPTOR_STRERROR() \ 172 __lsan::ScopedInterceptorDisabler disabler 173 #endif 174 175 #include "sanitizer_common/sanitizer_common_interceptors.inc" 176 #include "sanitizer_common/sanitizer_signal_interceptors.inc" 177 178 // Syscall interceptors don't have contexts, we don't support suppressions 179 // for them. 180 #define COMMON_SYSCALL_PRE_READ_RANGE(p, s) ASAN_READ_RANGE(nullptr, p, s) 181 #define COMMON_SYSCALL_PRE_WRITE_RANGE(p, s) ASAN_WRITE_RANGE(nullptr, p, s) 182 #define COMMON_SYSCALL_POST_READ_RANGE(p, s) \ 183 do { \ 184 (void)(p); \ 185 (void)(s); \ 186 } while (false) 187 #define COMMON_SYSCALL_POST_WRITE_RANGE(p, s) \ 188 do { \ 189 (void)(p); \ 190 (void)(s); \ 191 } while (false) 192 #include "sanitizer_common/sanitizer_common_syscalls.inc" 193 #include "sanitizer_common/sanitizer_syscalls_netbsd.inc" 194 195 #if ASAN_INTERCEPT_PTHREAD_CREATE 196 static thread_return_t THREAD_CALLING_CONV asan_thread_start(void *arg) { 197 AsanThread *t = (AsanThread *)arg; 198 SetCurrentThread(t); 199 return t->ThreadStart(GetTid()); 200 } 201 202 INTERCEPTOR(int, pthread_create, void *thread, 203 void *attr, void *(*start_routine)(void*), void *arg) { 204 EnsureMainThreadIDIsCorrect(); 205 // Strict init-order checking is thread-hostile. 206 if (flags()->strict_init_order) 207 StopInitOrderChecking(); 208 GET_STACK_TRACE_THREAD; 209 int detached = 0; 210 if (attr) 211 REAL(pthread_attr_getdetachstate)(attr, &detached); 212 213 u32 current_tid = GetCurrentTidOrInvalid(); 214 AsanThread *t = 215 AsanThread::Create(start_routine, arg, current_tid, &stack, detached); 216 217 int result; 218 { 219 // Ignore all allocations made by pthread_create: thread stack/TLS may be 220 // stored by pthread for future reuse even after thread destruction, and 221 // the linked list it's stored in doesn't even hold valid pointers to the 222 // objects, the latter are calculated by obscure pointer arithmetic. 223 #if CAN_SANITIZE_LEAKS 224 __lsan::ScopedInterceptorDisabler disabler; 225 #endif 226 result = REAL(pthread_create)(thread, attr, asan_thread_start, t); 227 } 228 if (result != 0) { 229 // If the thread didn't start delete the AsanThread to avoid leaking it. 230 // Note AsanThreadContexts never get destroyed so the AsanThreadContext 231 // that was just created for the AsanThread is wasted. 232 t->Destroy(); 233 } 234 return result; 235 } 236 237 INTERCEPTOR(int, pthread_join, void *t, void **arg) { 238 return real_pthread_join(t, arg); 239 } 240 241 DEFINE_REAL_PTHREAD_FUNCTIONS 242 #endif // ASAN_INTERCEPT_PTHREAD_CREATE 243 244 #if ASAN_INTERCEPT_SWAPCONTEXT 245 static void ClearShadowMemoryForContextStack(uptr stack, uptr ssize) { 246 // Only clear if we know the stack. This should be true only for contexts 247 // created with makecontext(). 248 if (!ssize) 249 return; 250 // Align to page size. 251 uptr PageSize = GetPageSizeCached(); 252 uptr bottom = RoundDownTo(stack, PageSize); 253 if (!AddrIsInMem(bottom)) 254 return; 255 ssize += stack - bottom; 256 ssize = RoundUpTo(ssize, PageSize); 257 PoisonShadow(bottom, ssize, 0); 258 } 259 260 INTERCEPTOR(int, getcontext, struct ucontext_t *ucp) { 261 // API does not requires to have ucp clean, and sets only part of fields. We 262 // use ucp->uc_stack to unpoison new stack. We prefer to have zeroes then 263 // uninitialized bytes. 264 ResetContextStack(ucp); 265 return REAL(getcontext)(ucp); 266 } 267 268 INTERCEPTOR(int, swapcontext, struct ucontext_t *oucp, 269 struct ucontext_t *ucp) { 270 static bool reported_warning = false; 271 if (!reported_warning) { 272 Report("WARNING: ASan doesn't fully support makecontext/swapcontext " 273 "functions and may produce false positives in some cases!\n"); 274 reported_warning = true; 275 } 276 // Clear shadow memory for new context (it may share stack 277 // with current context). 278 uptr stack, ssize; 279 ReadContextStack(ucp, &stack, &ssize); 280 ClearShadowMemoryForContextStack(stack, ssize); 281 282 // See getcontext interceptor. 283 ResetContextStack(oucp); 284 285 # if __has_attribute(__indirect_return__) && \ 286 (defined(__x86_64__) || defined(__i386__)) 287 int (*real_swapcontext)(struct ucontext_t *, struct ucontext_t *) 288 __attribute__((__indirect_return__)) = REAL(swapcontext); 289 int res = real_swapcontext(oucp, ucp); 290 # else 291 int res = REAL(swapcontext)(oucp, ucp); 292 # endif 293 // swapcontext technically does not return, but program may swap context to 294 // "oucp" later, that would look as if swapcontext() returned 0. 295 // We need to clear shadow for ucp once again, as it may be in arbitrary 296 // state. 297 ClearShadowMemoryForContextStack(stack, ssize); 298 return res; 299 } 300 #endif // ASAN_INTERCEPT_SWAPCONTEXT 301 302 #if SANITIZER_NETBSD 303 #define longjmp __longjmp14 304 #define siglongjmp __siglongjmp14 305 #endif 306 307 INTERCEPTOR(void, longjmp, void *env, int val) { 308 __asan_handle_no_return(); 309 REAL(longjmp)(env, val); 310 } 311 312 #if ASAN_INTERCEPT__LONGJMP 313 INTERCEPTOR(void, _longjmp, void *env, int val) { 314 __asan_handle_no_return(); 315 REAL(_longjmp)(env, val); 316 } 317 #endif 318 319 #if ASAN_INTERCEPT___LONGJMP_CHK 320 INTERCEPTOR(void, __longjmp_chk, void *env, int val) { 321 __asan_handle_no_return(); 322 REAL(__longjmp_chk)(env, val); 323 } 324 #endif 325 326 #if ASAN_INTERCEPT_SIGLONGJMP 327 INTERCEPTOR(void, siglongjmp, void *env, int val) { 328 __asan_handle_no_return(); 329 REAL(siglongjmp)(env, val); 330 } 331 #endif 332 333 #if ASAN_INTERCEPT___CXA_THROW 334 INTERCEPTOR(void, __cxa_throw, void *a, void *b, void *c) { 335 CHECK(REAL(__cxa_throw)); 336 __asan_handle_no_return(); 337 REAL(__cxa_throw)(a, b, c); 338 } 339 #endif 340 341 #if ASAN_INTERCEPT___CXA_RETHROW_PRIMARY_EXCEPTION 342 INTERCEPTOR(void, __cxa_rethrow_primary_exception, void *a) { 343 CHECK(REAL(__cxa_rethrow_primary_exception)); 344 __asan_handle_no_return(); 345 REAL(__cxa_rethrow_primary_exception)(a); 346 } 347 #endif 348 349 #if ASAN_INTERCEPT__UNWIND_RAISEEXCEPTION 350 INTERCEPTOR(_Unwind_Reason_Code, _Unwind_RaiseException, 351 _Unwind_Exception *object) { 352 CHECK(REAL(_Unwind_RaiseException)); 353 __asan_handle_no_return(); 354 return REAL(_Unwind_RaiseException)(object); 355 } 356 #endif 357 358 #if ASAN_INTERCEPT__SJLJ_UNWIND_RAISEEXCEPTION 359 INTERCEPTOR(_Unwind_Reason_Code, _Unwind_SjLj_RaiseException, 360 _Unwind_Exception *object) { 361 CHECK(REAL(_Unwind_SjLj_RaiseException)); 362 __asan_handle_no_return(); 363 return REAL(_Unwind_SjLj_RaiseException)(object); 364 } 365 #endif 366 367 #if ASAN_INTERCEPT_INDEX 368 # if ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX 369 INTERCEPTOR(char*, index, const char *string, int c) 370 ALIAS(WRAPPER_NAME(strchr)); 371 # else 372 # if SANITIZER_APPLE 373 DECLARE_REAL(char*, index, const char *string, int c) 374 OVERRIDE_FUNCTION(index, strchr); 375 # else 376 DEFINE_REAL(char*, index, const char *string, int c) 377 # endif 378 # endif 379 #endif // ASAN_INTERCEPT_INDEX 380 381 // For both strcat() and strncat() we need to check the validity of |to| 382 // argument irrespective of the |from| length. 383 INTERCEPTOR(char *, strcat, char *to, const char *from) { 384 void *ctx; 385 ASAN_INTERCEPTOR_ENTER(ctx, strcat); 386 ENSURE_ASAN_INITED(); 387 if (flags()->replace_str) { 388 uptr from_length = internal_strlen(from); 389 ASAN_READ_RANGE(ctx, from, from_length + 1); 390 uptr to_length = internal_strlen(to); 391 ASAN_READ_STRING_OF_LEN(ctx, to, to_length, to_length); 392 ASAN_WRITE_RANGE(ctx, to + to_length, from_length + 1); 393 // If the copying actually happens, the |from| string should not overlap 394 // with the resulting string starting at |to|, which has a length of 395 // to_length + from_length + 1. 396 if (from_length > 0) { 397 CHECK_RANGES_OVERLAP("strcat", to, from_length + to_length + 1, from, 398 from_length + 1); 399 } 400 } 401 return REAL(strcat)(to, from); 402 } 403 404 INTERCEPTOR(char*, strncat, char *to, const char *from, uptr size) { 405 void *ctx; 406 ASAN_INTERCEPTOR_ENTER(ctx, strncat); 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(ctx, from, copy_length); 412 uptr to_length = internal_strlen(to); 413 ASAN_READ_STRING_OF_LEN(ctx, to, to_length, to_length); 414 ASAN_WRITE_RANGE(ctx, 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 423 INTERCEPTOR(char *, strcpy, char *to, const char *from) { 424 void *ctx; 425 ASAN_INTERCEPTOR_ENTER(ctx, strcpy); 426 #if SANITIZER_APPLE 427 if (UNLIKELY(!asan_inited)) 428 return REAL(strcpy)(to, from); 429 #endif 430 // strcpy is called from malloc_default_purgeable_zone() 431 // in __asan::ReplaceSystemAlloc() on Mac. 432 if (asan_init_is_running) { 433 return REAL(strcpy)(to, from); 434 } 435 ENSURE_ASAN_INITED(); 436 if (flags()->replace_str) { 437 uptr from_size = internal_strlen(from) + 1; 438 CHECK_RANGES_OVERLAP("strcpy", to, from_size, from, from_size); 439 ASAN_READ_RANGE(ctx, from, from_size); 440 ASAN_WRITE_RANGE(ctx, to, from_size); 441 } 442 return REAL(strcpy)(to, from); 443 } 444 445 INTERCEPTOR(char*, strdup, const char *s) { 446 void *ctx; 447 ASAN_INTERCEPTOR_ENTER(ctx, strdup); 448 if (UNLIKELY(!asan_inited)) return internal_strdup(s); 449 ENSURE_ASAN_INITED(); 450 uptr length = internal_strlen(s); 451 if (flags()->replace_str) { 452 ASAN_READ_RANGE(ctx, s, length + 1); 453 } 454 GET_STACK_TRACE_MALLOC; 455 void *new_mem = asan_malloc(length + 1, &stack); 456 REAL(memcpy)(new_mem, s, length + 1); 457 return reinterpret_cast<char*>(new_mem); 458 } 459 460 #if ASAN_INTERCEPT___STRDUP 461 INTERCEPTOR(char*, __strdup, const char *s) { 462 void *ctx; 463 ASAN_INTERCEPTOR_ENTER(ctx, strdup); 464 if (UNLIKELY(!asan_inited)) return internal_strdup(s); 465 ENSURE_ASAN_INITED(); 466 uptr length = internal_strlen(s); 467 if (flags()->replace_str) { 468 ASAN_READ_RANGE(ctx, s, length + 1); 469 } 470 GET_STACK_TRACE_MALLOC; 471 void *new_mem = asan_malloc(length + 1, &stack); 472 REAL(memcpy)(new_mem, s, length + 1); 473 return reinterpret_cast<char*>(new_mem); 474 } 475 #endif // ASAN_INTERCEPT___STRDUP 476 477 INTERCEPTOR(char*, strncpy, char *to, const char *from, uptr size) { 478 void *ctx; 479 ASAN_INTERCEPTOR_ENTER(ctx, strncpy); 480 ENSURE_ASAN_INITED(); 481 if (flags()->replace_str) { 482 uptr from_size = Min(size, MaybeRealStrnlen(from, size) + 1); 483 CHECK_RANGES_OVERLAP("strncpy", to, from_size, from, from_size); 484 ASAN_READ_RANGE(ctx, from, from_size); 485 ASAN_WRITE_RANGE(ctx, to, size); 486 } 487 return REAL(strncpy)(to, from, size); 488 } 489 490 INTERCEPTOR(long, strtol, const char *nptr, char **endptr, int base) { 491 void *ctx; 492 ASAN_INTERCEPTOR_ENTER(ctx, strtol); 493 ENSURE_ASAN_INITED(); 494 if (!flags()->replace_str) { 495 return REAL(strtol)(nptr, endptr, base); 496 } 497 char *real_endptr; 498 long result = REAL(strtol)(nptr, &real_endptr, base); 499 StrtolFixAndCheck(ctx, nptr, endptr, real_endptr, base); 500 return result; 501 } 502 503 INTERCEPTOR(int, atoi, const char *nptr) { 504 void *ctx; 505 ASAN_INTERCEPTOR_ENTER(ctx, atoi); 506 #if SANITIZER_APPLE 507 if (UNLIKELY(!asan_inited)) return REAL(atoi)(nptr); 508 #endif 509 ENSURE_ASAN_INITED(); 510 if (!flags()->replace_str) { 511 return REAL(atoi)(nptr); 512 } 513 char *real_endptr; 514 // "man atoi" tells that behavior of atoi(nptr) is the same as 515 // strtol(nptr, 0, 10), i.e. it sets errno to ERANGE if the 516 // parsed integer can't be stored in *long* type (even if it's 517 // different from int). So, we just imitate this behavior. 518 int result = REAL(strtol)(nptr, &real_endptr, 10); 519 FixRealStrtolEndptr(nptr, &real_endptr); 520 ASAN_READ_STRING(ctx, nptr, (real_endptr - nptr) + 1); 521 return result; 522 } 523 524 INTERCEPTOR(long, atol, const char *nptr) { 525 void *ctx; 526 ASAN_INTERCEPTOR_ENTER(ctx, atol); 527 #if SANITIZER_APPLE 528 if (UNLIKELY(!asan_inited)) return REAL(atol)(nptr); 529 #endif 530 ENSURE_ASAN_INITED(); 531 if (!flags()->replace_str) { 532 return REAL(atol)(nptr); 533 } 534 char *real_endptr; 535 long result = REAL(strtol)(nptr, &real_endptr, 10); 536 FixRealStrtolEndptr(nptr, &real_endptr); 537 ASAN_READ_STRING(ctx, nptr, (real_endptr - nptr) + 1); 538 return result; 539 } 540 541 #if ASAN_INTERCEPT_ATOLL_AND_STRTOLL 542 INTERCEPTOR(long long, strtoll, const char *nptr, char **endptr, int base) { 543 void *ctx; 544 ASAN_INTERCEPTOR_ENTER(ctx, strtoll); 545 ENSURE_ASAN_INITED(); 546 if (!flags()->replace_str) { 547 return REAL(strtoll)(nptr, endptr, base); 548 } 549 char *real_endptr; 550 long long result = REAL(strtoll)(nptr, &real_endptr, base); 551 StrtolFixAndCheck(ctx, nptr, endptr, real_endptr, base); 552 return result; 553 } 554 555 INTERCEPTOR(long long, atoll, const char *nptr) { 556 void *ctx; 557 ASAN_INTERCEPTOR_ENTER(ctx, atoll); 558 ENSURE_ASAN_INITED(); 559 if (!flags()->replace_str) { 560 return REAL(atoll)(nptr); 561 } 562 char *real_endptr; 563 long long result = REAL(strtoll)(nptr, &real_endptr, 10); 564 FixRealStrtolEndptr(nptr, &real_endptr); 565 ASAN_READ_STRING(ctx, nptr, (real_endptr - nptr) + 1); 566 return result; 567 } 568 #endif // ASAN_INTERCEPT_ATOLL_AND_STRTOLL 569 570 #if ASAN_INTERCEPT___CXA_ATEXIT || ASAN_INTERCEPT_ATEXIT 571 static void AtCxaAtexit(void *unused) { 572 (void)unused; 573 StopInitOrderChecking(); 574 } 575 #endif 576 577 #if ASAN_INTERCEPT___CXA_ATEXIT 578 INTERCEPTOR(int, __cxa_atexit, void (*func)(void *), void *arg, 579 void *dso_handle) { 580 #if SANITIZER_APPLE 581 if (UNLIKELY(!asan_inited)) return REAL(__cxa_atexit)(func, arg, dso_handle); 582 #endif 583 ENSURE_ASAN_INITED(); 584 #if CAN_SANITIZE_LEAKS 585 __lsan::ScopedInterceptorDisabler disabler; 586 #endif 587 int res = REAL(__cxa_atexit)(func, arg, dso_handle); 588 REAL(__cxa_atexit)(AtCxaAtexit, nullptr, nullptr); 589 return res; 590 } 591 #endif // ASAN_INTERCEPT___CXA_ATEXIT 592 593 #if ASAN_INTERCEPT_ATEXIT 594 INTERCEPTOR(int, atexit, void (*func)()) { 595 ENSURE_ASAN_INITED(); 596 #if CAN_SANITIZE_LEAKS 597 __lsan::ScopedInterceptorDisabler disabler; 598 #endif 599 // Avoid calling real atexit as it is unreachable on at least on Linux. 600 int res = REAL(__cxa_atexit)((void (*)(void *a))func, nullptr, nullptr); 601 REAL(__cxa_atexit)(AtCxaAtexit, nullptr, nullptr); 602 return res; 603 } 604 #endif 605 606 #if ASAN_INTERCEPT_PTHREAD_ATFORK 607 extern "C" { 608 extern int _pthread_atfork(void (*prepare)(), void (*parent)(), 609 void (*child)()); 610 }; 611 612 INTERCEPTOR(int, pthread_atfork, void (*prepare)(), void (*parent)(), 613 void (*child)()) { 614 #if CAN_SANITIZE_LEAKS 615 __lsan::ScopedInterceptorDisabler disabler; 616 #endif 617 // REAL(pthread_atfork) cannot be called due to symbol indirections at least 618 // on NetBSD 619 return _pthread_atfork(prepare, parent, child); 620 } 621 #endif 622 623 #if ASAN_INTERCEPT_VFORK 624 DEFINE_REAL(int, vfork) 625 DECLARE_EXTERN_INTERCEPTOR_AND_WRAPPER(int, vfork) 626 #endif 627 628 // ---------------------- InitializeAsanInterceptors ---------------- {{{1 629 namespace __asan { 630 void InitializeAsanInterceptors() { 631 static bool was_called_once; 632 CHECK(!was_called_once); 633 was_called_once = true; 634 InitializeCommonInterceptors(); 635 InitializeSignalInterceptors(); 636 637 // Intercept str* functions. 638 ASAN_INTERCEPT_FUNC(strcat); 639 ASAN_INTERCEPT_FUNC(strcpy); 640 ASAN_INTERCEPT_FUNC(strncat); 641 ASAN_INTERCEPT_FUNC(strncpy); 642 ASAN_INTERCEPT_FUNC(strdup); 643 #if ASAN_INTERCEPT___STRDUP 644 ASAN_INTERCEPT_FUNC(__strdup); 645 #endif 646 #if ASAN_INTERCEPT_INDEX && ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX 647 ASAN_INTERCEPT_FUNC(index); 648 #endif 649 650 ASAN_INTERCEPT_FUNC(atoi); 651 ASAN_INTERCEPT_FUNC(atol); 652 ASAN_INTERCEPT_FUNC(strtol); 653 #if ASAN_INTERCEPT_ATOLL_AND_STRTOLL 654 ASAN_INTERCEPT_FUNC(atoll); 655 ASAN_INTERCEPT_FUNC(strtoll); 656 #endif 657 658 // Intecept jump-related functions. 659 ASAN_INTERCEPT_FUNC(longjmp); 660 661 #if ASAN_INTERCEPT_SWAPCONTEXT 662 ASAN_INTERCEPT_FUNC(getcontext); 663 ASAN_INTERCEPT_FUNC(swapcontext); 664 #endif 665 #if ASAN_INTERCEPT__LONGJMP 666 ASAN_INTERCEPT_FUNC(_longjmp); 667 #endif 668 #if ASAN_INTERCEPT___LONGJMP_CHK 669 ASAN_INTERCEPT_FUNC(__longjmp_chk); 670 #endif 671 #if ASAN_INTERCEPT_SIGLONGJMP 672 ASAN_INTERCEPT_FUNC(siglongjmp); 673 #endif 674 675 // Intercept exception handling functions. 676 #if ASAN_INTERCEPT___CXA_THROW 677 ASAN_INTERCEPT_FUNC(__cxa_throw); 678 #endif 679 #if ASAN_INTERCEPT___CXA_RETHROW_PRIMARY_EXCEPTION 680 ASAN_INTERCEPT_FUNC(__cxa_rethrow_primary_exception); 681 #endif 682 // Indirectly intercept std::rethrow_exception. 683 #if ASAN_INTERCEPT__UNWIND_RAISEEXCEPTION 684 INTERCEPT_FUNCTION(_Unwind_RaiseException); 685 #endif 686 // Indirectly intercept std::rethrow_exception. 687 #if ASAN_INTERCEPT__UNWIND_SJLJ_RAISEEXCEPTION 688 INTERCEPT_FUNCTION(_Unwind_SjLj_RaiseException); 689 #endif 690 691 // Intercept threading-related functions 692 #if ASAN_INTERCEPT_PTHREAD_CREATE 693 // TODO: this should probably have an unversioned fallback for newer arches? 694 #if defined(ASAN_PTHREAD_CREATE_VERSION) 695 ASAN_INTERCEPT_FUNC_VER(pthread_create, ASAN_PTHREAD_CREATE_VERSION); 696 #else 697 ASAN_INTERCEPT_FUNC(pthread_create); 698 #endif 699 ASAN_INTERCEPT_FUNC(pthread_join); 700 #endif 701 702 // Intercept atexit function. 703 #if ASAN_INTERCEPT___CXA_ATEXIT 704 ASAN_INTERCEPT_FUNC(__cxa_atexit); 705 #endif 706 707 #if ASAN_INTERCEPT_ATEXIT 708 ASAN_INTERCEPT_FUNC(atexit); 709 #endif 710 711 #if ASAN_INTERCEPT_PTHREAD_ATFORK 712 ASAN_INTERCEPT_FUNC(pthread_atfork); 713 #endif 714 715 #if ASAN_INTERCEPT_VFORK 716 ASAN_INTERCEPT_FUNC(vfork); 717 #endif 718 719 InitializePlatformInterceptors(); 720 721 VReport(1, "AddressSanitizer: libc interceptors initialized\n"); 722 } 723 724 } // namespace __asan 725 726 #endif // !SANITIZER_FUCHSIA 727