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