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), REAL(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_MAC && 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_ON_DLOPEN(filename, flag) \ 134 do { \ 135 if (flags()->strict_init_order) \ 136 StopInitOrderChecking(); \ 137 CheckNoDeepBind(filename, flag); \ 138 } while (false) 139 #define COMMON_INTERCEPTOR_ON_EXIT(ctx) OnExit() 140 #define COMMON_INTERCEPTOR_LIBRARY_LOADED(filename, handle) 141 #define COMMON_INTERCEPTOR_LIBRARY_UNLOADED() 142 #define COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED (!asan_inited) 143 #define COMMON_INTERCEPTOR_GET_TLS_RANGE(begin, end) \ 144 if (AsanThread *t = GetCurrentThread()) { \ 145 *begin = t->tls_begin(); \ 146 *end = t->tls_end(); \ 147 } else { \ 148 *begin = *end = 0; \ 149 } 150 151 #define COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, to, from, size) \ 152 do { \ 153 ASAN_INTERCEPTOR_ENTER(ctx, memmove); \ 154 ASAN_MEMMOVE_IMPL(ctx, to, from, size); \ 155 } while (false) 156 157 #define COMMON_INTERCEPTOR_MEMCPY_IMPL(ctx, to, from, size) \ 158 do { \ 159 ASAN_INTERCEPTOR_ENTER(ctx, memcpy); \ 160 ASAN_MEMCPY_IMPL(ctx, to, from, size); \ 161 } while (false) 162 163 #define COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, c, size) \ 164 do { \ 165 ASAN_INTERCEPTOR_ENTER(ctx, memset); \ 166 ASAN_MEMSET_IMPL(ctx, block, c, size); \ 167 } while (false) 168 169 #if CAN_SANITIZE_LEAKS 170 #define COMMON_INTERCEPTOR_STRERROR() \ 171 __lsan::ScopedInterceptorDisabler disabler 172 #endif 173 174 #include "sanitizer_common/sanitizer_common_interceptors.inc" 175 #include "sanitizer_common/sanitizer_signal_interceptors.inc" 176 177 // Syscall interceptors don't have contexts, we don't support suppressions 178 // for them. 179 #define COMMON_SYSCALL_PRE_READ_RANGE(p, s) ASAN_READ_RANGE(nullptr, p, s) 180 #define COMMON_SYSCALL_PRE_WRITE_RANGE(p, s) ASAN_WRITE_RANGE(nullptr, p, s) 181 #define COMMON_SYSCALL_POST_READ_RANGE(p, s) \ 182 do { \ 183 (void)(p); \ 184 (void)(s); \ 185 } while (false) 186 #define COMMON_SYSCALL_POST_WRITE_RANGE(p, s) \ 187 do { \ 188 (void)(p); \ 189 (void)(s); \ 190 } while (false) 191 #include "sanitizer_common/sanitizer_common_syscalls.inc" 192 #include "sanitizer_common/sanitizer_syscalls_netbsd.inc" 193 194 #if ASAN_INTERCEPT_PTHREAD_CREATE 195 static thread_return_t THREAD_CALLING_CONV asan_thread_start(void *arg) { 196 AsanThread *t = (AsanThread *)arg; 197 SetCurrentThread(t); 198 return t->ThreadStart(GetTid()); 199 } 200 201 INTERCEPTOR(int, pthread_create, void *thread, 202 void *attr, void *(*start_routine)(void*), void *arg) { 203 EnsureMainThreadIDIsCorrect(); 204 // Strict init-order checking is thread-hostile. 205 if (flags()->strict_init_order) 206 StopInitOrderChecking(); 207 GET_STACK_TRACE_THREAD; 208 int detached = 0; 209 if (attr) 210 REAL(pthread_attr_getdetachstate)(attr, &detached); 211 212 u32 current_tid = GetCurrentTidOrInvalid(); 213 AsanThread *t = 214 AsanThread::Create(start_routine, arg, current_tid, &stack, detached); 215 216 int result; 217 { 218 // Ignore all allocations made by pthread_create: thread stack/TLS may be 219 // stored by pthread for future reuse even after thread destruction, and 220 // the linked list it's stored in doesn't even hold valid pointers to the 221 // objects, the latter are calculated by obscure pointer arithmetic. 222 #if CAN_SANITIZE_LEAKS 223 __lsan::ScopedInterceptorDisabler disabler; 224 #endif 225 result = REAL(pthread_create)(thread, attr, asan_thread_start, t); 226 } 227 if (result != 0) { 228 // If the thread didn't start delete the AsanThread to avoid leaking it. 229 // Note AsanThreadContexts never get destroyed so the AsanThreadContext 230 // that was just created for the AsanThread is wasted. 231 t->Destroy(); 232 } 233 return result; 234 } 235 236 INTERCEPTOR(int, pthread_join, void *t, void **arg) { 237 return real_pthread_join(t, arg); 238 } 239 240 DEFINE_REAL_PTHREAD_FUNCTIONS 241 #endif // ASAN_INTERCEPT_PTHREAD_CREATE 242 243 #if ASAN_INTERCEPT_SWAPCONTEXT 244 static void ClearShadowMemoryForContextStack(uptr stack, uptr ssize) { 245 // Align to page size. 246 uptr PageSize = GetPageSizeCached(); 247 uptr bottom = stack & ~(PageSize - 1); 248 ssize += stack - bottom; 249 ssize = RoundUpTo(ssize, PageSize); 250 static const uptr kMaxSaneContextStackSize = 1 << 22; // 4 Mb 251 if (AddrIsInMem(bottom) && ssize && ssize <= kMaxSaneContextStackSize) { 252 PoisonShadow(bottom, ssize, 0); 253 } 254 } 255 256 INTERCEPTOR(int, swapcontext, struct ucontext_t *oucp, 257 struct ucontext_t *ucp) { 258 static bool reported_warning = false; 259 if (!reported_warning) { 260 Report("WARNING: ASan doesn't fully support makecontext/swapcontext " 261 "functions and may produce false positives in some cases!\n"); 262 reported_warning = true; 263 } 264 // Clear shadow memory for new context (it may share stack 265 // with current context). 266 uptr stack, ssize; 267 ReadContextStack(ucp, &stack, &ssize); 268 ClearShadowMemoryForContextStack(stack, ssize); 269 #if __has_attribute(__indirect_return__) && \ 270 (defined(__x86_64__) || defined(__i386__)) 271 int (*real_swapcontext)(struct ucontext_t *, struct ucontext_t *) 272 __attribute__((__indirect_return__)) 273 = REAL(swapcontext); 274 int res = real_swapcontext(oucp, ucp); 275 #else 276 int res = REAL(swapcontext)(oucp, ucp); 277 #endif 278 // swapcontext technically does not return, but program may swap context to 279 // "oucp" later, that would look as if swapcontext() returned 0. 280 // We need to clear shadow for ucp once again, as it may be in arbitrary 281 // state. 282 ClearShadowMemoryForContextStack(stack, ssize); 283 return res; 284 } 285 #endif // ASAN_INTERCEPT_SWAPCONTEXT 286 287 #if SANITIZER_NETBSD 288 #define longjmp __longjmp14 289 #define siglongjmp __siglongjmp14 290 #endif 291 292 INTERCEPTOR(void, longjmp, void *env, int val) { 293 __asan_handle_no_return(); 294 REAL(longjmp)(env, val); 295 } 296 297 #if ASAN_INTERCEPT__LONGJMP 298 INTERCEPTOR(void, _longjmp, void *env, int val) { 299 __asan_handle_no_return(); 300 REAL(_longjmp)(env, val); 301 } 302 #endif 303 304 #if ASAN_INTERCEPT___LONGJMP_CHK 305 INTERCEPTOR(void, __longjmp_chk, void *env, int val) { 306 __asan_handle_no_return(); 307 REAL(__longjmp_chk)(env, val); 308 } 309 #endif 310 311 #if ASAN_INTERCEPT_SIGLONGJMP 312 INTERCEPTOR(void, siglongjmp, void *env, int val) { 313 __asan_handle_no_return(); 314 REAL(siglongjmp)(env, val); 315 } 316 #endif 317 318 #if ASAN_INTERCEPT___CXA_THROW 319 INTERCEPTOR(void, __cxa_throw, void *a, void *b, void *c) { 320 CHECK(REAL(__cxa_throw)); 321 __asan_handle_no_return(); 322 REAL(__cxa_throw)(a, b, c); 323 } 324 #endif 325 326 #if ASAN_INTERCEPT___CXA_RETHROW_PRIMARY_EXCEPTION 327 INTERCEPTOR(void, __cxa_rethrow_primary_exception, void *a) { 328 CHECK(REAL(__cxa_rethrow_primary_exception)); 329 __asan_handle_no_return(); 330 REAL(__cxa_rethrow_primary_exception)(a); 331 } 332 #endif 333 334 #if ASAN_INTERCEPT__UNWIND_RAISEEXCEPTION 335 INTERCEPTOR(_Unwind_Reason_Code, _Unwind_RaiseException, 336 _Unwind_Exception *object) { 337 CHECK(REAL(_Unwind_RaiseException)); 338 __asan_handle_no_return(); 339 return REAL(_Unwind_RaiseException)(object); 340 } 341 #endif 342 343 #if ASAN_INTERCEPT__SJLJ_UNWIND_RAISEEXCEPTION 344 INTERCEPTOR(_Unwind_Reason_Code, _Unwind_SjLj_RaiseException, 345 _Unwind_Exception *object) { 346 CHECK(REAL(_Unwind_SjLj_RaiseException)); 347 __asan_handle_no_return(); 348 return REAL(_Unwind_SjLj_RaiseException)(object); 349 } 350 #endif 351 352 #if ASAN_INTERCEPT_INDEX 353 # if ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX 354 INTERCEPTOR(char*, index, const char *string, int c) 355 ALIAS(WRAPPER_NAME(strchr)); 356 # else 357 # if SANITIZER_MAC 358 DECLARE_REAL(char*, index, const char *string, int c) 359 OVERRIDE_FUNCTION(index, strchr); 360 # else 361 DEFINE_REAL(char*, index, const char *string, int c) 362 # endif 363 # endif 364 #endif // ASAN_INTERCEPT_INDEX 365 366 // For both strcat() and strncat() we need to check the validity of |to| 367 // argument irrespective of the |from| length. 368 INTERCEPTOR(char *, strcat, char *to, const char *from) { 369 void *ctx; 370 ASAN_INTERCEPTOR_ENTER(ctx, strcat); 371 ENSURE_ASAN_INITED(); 372 if (flags()->replace_str) { 373 uptr from_length = REAL(strlen)(from); 374 ASAN_READ_RANGE(ctx, from, from_length + 1); 375 uptr to_length = REAL(strlen)(to); 376 ASAN_READ_STRING_OF_LEN(ctx, to, to_length, to_length); 377 ASAN_WRITE_RANGE(ctx, to + to_length, from_length + 1); 378 // If the copying actually happens, the |from| string should not overlap 379 // with the resulting string starting at |to|, which has a length of 380 // to_length + from_length + 1. 381 if (from_length > 0) { 382 CHECK_RANGES_OVERLAP("strcat", to, from_length + to_length + 1, from, 383 from_length + 1); 384 } 385 } 386 return REAL(strcat)(to, from); 387 } 388 389 INTERCEPTOR(char*, strncat, char *to, const char *from, uptr size) { 390 void *ctx; 391 ASAN_INTERCEPTOR_ENTER(ctx, strncat); 392 ENSURE_ASAN_INITED(); 393 if (flags()->replace_str) { 394 uptr from_length = MaybeRealStrnlen(from, size); 395 uptr copy_length = Min(size, from_length + 1); 396 ASAN_READ_RANGE(ctx, from, copy_length); 397 uptr to_length = REAL(strlen)(to); 398 ASAN_READ_STRING_OF_LEN(ctx, to, to_length, to_length); 399 ASAN_WRITE_RANGE(ctx, to + to_length, from_length + 1); 400 if (from_length > 0) { 401 CHECK_RANGES_OVERLAP("strncat", to, to_length + copy_length + 1, 402 from, copy_length); 403 } 404 } 405 return REAL(strncat)(to, from, size); 406 } 407 408 INTERCEPTOR(char *, strcpy, char *to, const char *from) { 409 void *ctx; 410 ASAN_INTERCEPTOR_ENTER(ctx, strcpy); 411 #if SANITIZER_MAC 412 if (UNLIKELY(!asan_inited)) 413 return REAL(strcpy)(to, from); 414 #endif 415 // strcpy is called from malloc_default_purgeable_zone() 416 // in __asan::ReplaceSystemAlloc() on Mac. 417 if (asan_init_is_running) { 418 return REAL(strcpy)(to, from); 419 } 420 ENSURE_ASAN_INITED(); 421 if (flags()->replace_str) { 422 uptr from_size = REAL(strlen)(from) + 1; 423 CHECK_RANGES_OVERLAP("strcpy", to, from_size, from, from_size); 424 ASAN_READ_RANGE(ctx, from, from_size); 425 ASAN_WRITE_RANGE(ctx, to, from_size); 426 } 427 return REAL(strcpy)(to, from); 428 } 429 430 INTERCEPTOR(char*, strdup, const char *s) { 431 void *ctx; 432 ASAN_INTERCEPTOR_ENTER(ctx, strdup); 433 if (UNLIKELY(!asan_inited)) return internal_strdup(s); 434 ENSURE_ASAN_INITED(); 435 uptr length = REAL(strlen)(s); 436 if (flags()->replace_str) { 437 ASAN_READ_RANGE(ctx, s, length + 1); 438 } 439 GET_STACK_TRACE_MALLOC; 440 void *new_mem = asan_malloc(length + 1, &stack); 441 REAL(memcpy)(new_mem, s, length + 1); 442 return reinterpret_cast<char*>(new_mem); 443 } 444 445 #if ASAN_INTERCEPT___STRDUP 446 INTERCEPTOR(char*, __strdup, const char *s) { 447 void *ctx; 448 ASAN_INTERCEPTOR_ENTER(ctx, strdup); 449 if (UNLIKELY(!asan_inited)) return internal_strdup(s); 450 ENSURE_ASAN_INITED(); 451 uptr length = REAL(strlen)(s); 452 if (flags()->replace_str) { 453 ASAN_READ_RANGE(ctx, s, length + 1); 454 } 455 GET_STACK_TRACE_MALLOC; 456 void *new_mem = asan_malloc(length + 1, &stack); 457 REAL(memcpy)(new_mem, s, length + 1); 458 return reinterpret_cast<char*>(new_mem); 459 } 460 #endif // ASAN_INTERCEPT___STRDUP 461 462 INTERCEPTOR(char*, strncpy, char *to, const char *from, uptr size) { 463 void *ctx; 464 ASAN_INTERCEPTOR_ENTER(ctx, strncpy); 465 ENSURE_ASAN_INITED(); 466 if (flags()->replace_str) { 467 uptr from_size = Min(size, MaybeRealStrnlen(from, size) + 1); 468 CHECK_RANGES_OVERLAP("strncpy", to, from_size, from, from_size); 469 ASAN_READ_RANGE(ctx, from, from_size); 470 ASAN_WRITE_RANGE(ctx, to, size); 471 } 472 return REAL(strncpy)(to, from, size); 473 } 474 475 INTERCEPTOR(long, strtol, const char *nptr, char **endptr, int base) { 476 void *ctx; 477 ASAN_INTERCEPTOR_ENTER(ctx, strtol); 478 ENSURE_ASAN_INITED(); 479 if (!flags()->replace_str) { 480 return REAL(strtol)(nptr, endptr, base); 481 } 482 char *real_endptr; 483 long result = REAL(strtol)(nptr, &real_endptr, base); 484 StrtolFixAndCheck(ctx, nptr, endptr, real_endptr, base); 485 return result; 486 } 487 488 INTERCEPTOR(int, atoi, const char *nptr) { 489 void *ctx; 490 ASAN_INTERCEPTOR_ENTER(ctx, atoi); 491 #if SANITIZER_MAC 492 if (UNLIKELY(!asan_inited)) return REAL(atoi)(nptr); 493 #endif 494 ENSURE_ASAN_INITED(); 495 if (!flags()->replace_str) { 496 return REAL(atoi)(nptr); 497 } 498 char *real_endptr; 499 // "man atoi" tells that behavior of atoi(nptr) is the same as 500 // strtol(nptr, 0, 10), i.e. it sets errno to ERANGE if the 501 // parsed integer can't be stored in *long* type (even if it's 502 // different from int). So, we just imitate this behavior. 503 int result = REAL(strtol)(nptr, &real_endptr, 10); 504 FixRealStrtolEndptr(nptr, &real_endptr); 505 ASAN_READ_STRING(ctx, nptr, (real_endptr - nptr) + 1); 506 return result; 507 } 508 509 INTERCEPTOR(long, atol, const char *nptr) { 510 void *ctx; 511 ASAN_INTERCEPTOR_ENTER(ctx, atol); 512 #if SANITIZER_MAC 513 if (UNLIKELY(!asan_inited)) return REAL(atol)(nptr); 514 #endif 515 ENSURE_ASAN_INITED(); 516 if (!flags()->replace_str) { 517 return REAL(atol)(nptr); 518 } 519 char *real_endptr; 520 long result = REAL(strtol)(nptr, &real_endptr, 10); 521 FixRealStrtolEndptr(nptr, &real_endptr); 522 ASAN_READ_STRING(ctx, nptr, (real_endptr - nptr) + 1); 523 return result; 524 } 525 526 #if ASAN_INTERCEPT_ATOLL_AND_STRTOLL 527 INTERCEPTOR(long long, strtoll, const char *nptr, char **endptr, int base) { 528 void *ctx; 529 ASAN_INTERCEPTOR_ENTER(ctx, strtoll); 530 ENSURE_ASAN_INITED(); 531 if (!flags()->replace_str) { 532 return REAL(strtoll)(nptr, endptr, base); 533 } 534 char *real_endptr; 535 long long result = REAL(strtoll)(nptr, &real_endptr, base); 536 StrtolFixAndCheck(ctx, nptr, endptr, real_endptr, base); 537 return result; 538 } 539 540 INTERCEPTOR(long long, atoll, const char *nptr) { 541 void *ctx; 542 ASAN_INTERCEPTOR_ENTER(ctx, atoll); 543 ENSURE_ASAN_INITED(); 544 if (!flags()->replace_str) { 545 return REAL(atoll)(nptr); 546 } 547 char *real_endptr; 548 long long result = REAL(strtoll)(nptr, &real_endptr, 10); 549 FixRealStrtolEndptr(nptr, &real_endptr); 550 ASAN_READ_STRING(ctx, nptr, (real_endptr - nptr) + 1); 551 return result; 552 } 553 #endif // ASAN_INTERCEPT_ATOLL_AND_STRTOLL 554 555 #if ASAN_INTERCEPT___CXA_ATEXIT || ASAN_INTERCEPT_ATEXIT 556 static void AtCxaAtexit(void *unused) { 557 (void)unused; 558 StopInitOrderChecking(); 559 } 560 #endif 561 562 #if ASAN_INTERCEPT___CXA_ATEXIT 563 INTERCEPTOR(int, __cxa_atexit, void (*func)(void *), void *arg, 564 void *dso_handle) { 565 #if SANITIZER_MAC 566 if (UNLIKELY(!asan_inited)) return REAL(__cxa_atexit)(func, arg, dso_handle); 567 #endif 568 ENSURE_ASAN_INITED(); 569 #if CAN_SANITIZE_LEAKS 570 __lsan::ScopedInterceptorDisabler disabler; 571 #endif 572 int res = REAL(__cxa_atexit)(func, arg, dso_handle); 573 REAL(__cxa_atexit)(AtCxaAtexit, nullptr, nullptr); 574 return res; 575 } 576 #endif // ASAN_INTERCEPT___CXA_ATEXIT 577 578 #if ASAN_INTERCEPT_ATEXIT 579 INTERCEPTOR(int, atexit, void (*func)()) { 580 ENSURE_ASAN_INITED(); 581 #if CAN_SANITIZE_LEAKS 582 __lsan::ScopedInterceptorDisabler disabler; 583 #endif 584 // Avoid calling real atexit as it is unrechable on at least on Linux. 585 int res = REAL(__cxa_atexit)((void (*)(void *a))func, nullptr, nullptr); 586 REAL(__cxa_atexit)(AtCxaAtexit, nullptr, nullptr); 587 return res; 588 } 589 #endif 590 591 #if ASAN_INTERCEPT_PTHREAD_ATFORK 592 extern "C" { 593 extern int _pthread_atfork(void (*prepare)(), void (*parent)(), 594 void (*child)()); 595 }; 596 597 INTERCEPTOR(int, pthread_atfork, void (*prepare)(), void (*parent)(), 598 void (*child)()) { 599 #if CAN_SANITIZE_LEAKS 600 __lsan::ScopedInterceptorDisabler disabler; 601 #endif 602 // REAL(pthread_atfork) cannot be called due to symbol indirections at least 603 // on NetBSD 604 return _pthread_atfork(prepare, parent, child); 605 } 606 #endif 607 608 #if ASAN_INTERCEPT_VFORK 609 DEFINE_REAL(int, vfork) 610 DECLARE_EXTERN_INTERCEPTOR_AND_WRAPPER(int, vfork) 611 #endif 612 613 // ---------------------- InitializeAsanInterceptors ---------------- {{{1 614 namespace __asan { 615 void InitializeAsanInterceptors() { 616 static bool was_called_once; 617 CHECK(!was_called_once); 618 was_called_once = true; 619 InitializeCommonInterceptors(); 620 InitializeSignalInterceptors(); 621 622 // Intercept str* functions. 623 ASAN_INTERCEPT_FUNC(strcat); 624 ASAN_INTERCEPT_FUNC(strcpy); 625 ASAN_INTERCEPT_FUNC(strncat); 626 ASAN_INTERCEPT_FUNC(strncpy); 627 ASAN_INTERCEPT_FUNC(strdup); 628 #if ASAN_INTERCEPT___STRDUP 629 ASAN_INTERCEPT_FUNC(__strdup); 630 #endif 631 #if ASAN_INTERCEPT_INDEX && ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX 632 ASAN_INTERCEPT_FUNC(index); 633 #endif 634 635 ASAN_INTERCEPT_FUNC(atoi); 636 ASAN_INTERCEPT_FUNC(atol); 637 ASAN_INTERCEPT_FUNC(strtol); 638 #if ASAN_INTERCEPT_ATOLL_AND_STRTOLL 639 ASAN_INTERCEPT_FUNC(atoll); 640 ASAN_INTERCEPT_FUNC(strtoll); 641 #endif 642 643 // Intecept jump-related functions. 644 ASAN_INTERCEPT_FUNC(longjmp); 645 646 #if ASAN_INTERCEPT_SWAPCONTEXT 647 ASAN_INTERCEPT_FUNC(swapcontext); 648 #endif 649 #if ASAN_INTERCEPT__LONGJMP 650 ASAN_INTERCEPT_FUNC(_longjmp); 651 #endif 652 #if ASAN_INTERCEPT___LONGJMP_CHK 653 ASAN_INTERCEPT_FUNC(__longjmp_chk); 654 #endif 655 #if ASAN_INTERCEPT_SIGLONGJMP 656 ASAN_INTERCEPT_FUNC(siglongjmp); 657 #endif 658 659 // Intercept exception handling functions. 660 #if ASAN_INTERCEPT___CXA_THROW 661 ASAN_INTERCEPT_FUNC(__cxa_throw); 662 #endif 663 #if ASAN_INTERCEPT___CXA_RETHROW_PRIMARY_EXCEPTION 664 ASAN_INTERCEPT_FUNC(__cxa_rethrow_primary_exception); 665 #endif 666 // Indirectly intercept std::rethrow_exception. 667 #if ASAN_INTERCEPT__UNWIND_RAISEEXCEPTION 668 INTERCEPT_FUNCTION(_Unwind_RaiseException); 669 #endif 670 // Indirectly intercept std::rethrow_exception. 671 #if ASAN_INTERCEPT__UNWIND_SJLJ_RAISEEXCEPTION 672 INTERCEPT_FUNCTION(_Unwind_SjLj_RaiseException); 673 #endif 674 675 // Intercept threading-related functions 676 #if ASAN_INTERCEPT_PTHREAD_CREATE 677 // TODO: this should probably have an unversioned fallback for newer arches? 678 #if defined(ASAN_PTHREAD_CREATE_VERSION) 679 ASAN_INTERCEPT_FUNC_VER(pthread_create, ASAN_PTHREAD_CREATE_VERSION); 680 #else 681 ASAN_INTERCEPT_FUNC(pthread_create); 682 #endif 683 ASAN_INTERCEPT_FUNC(pthread_join); 684 #endif 685 686 // Intercept atexit function. 687 #if ASAN_INTERCEPT___CXA_ATEXIT 688 ASAN_INTERCEPT_FUNC(__cxa_atexit); 689 #endif 690 691 #if ASAN_INTERCEPT_ATEXIT 692 ASAN_INTERCEPT_FUNC(atexit); 693 #endif 694 695 #if ASAN_INTERCEPT_PTHREAD_ATFORK 696 ASAN_INTERCEPT_FUNC(pthread_atfork); 697 #endif 698 699 #if ASAN_INTERCEPT_VFORK 700 ASAN_INTERCEPT_FUNC(vfork); 701 #endif 702 703 InitializePlatformInterceptors(); 704 705 VReport(1, "AddressSanitizer: libc interceptors initialized\n"); 706 } 707 708 } // namespace __asan 709 710 #endif // !SANITIZER_FUCHSIA 711