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 46namespace __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 55static 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 64void SetThreadName(const char *name) { 65 AsanThread *t = GetCurrentThread(); 66 if (t) 67 asanThreadRegistry().SetThreadName(t->tid(), name); 68} 69 70int 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 82using namespace __asan; 83 84DECLARE_REAL_AND_INTERCEPTOR(void *, malloc, uptr) 85DECLARE_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 196static 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 202INTERCEPTOR(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 237INTERCEPTOR(int, pthread_join, void *t, void **arg) { 238 return real_pthread_join(t, arg); 239} 240 241DEFINE_REAL_PTHREAD_FUNCTIONS 242#endif // ASAN_INTERCEPT_PTHREAD_CREATE 243 244#if ASAN_INTERCEPT_SWAPCONTEXT 245static 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 260INTERCEPTOR(void, makecontext, struct ucontext_t *ucp, void (*func)(), int argc, 261 ...) { 262 va_list ap; 263 uptr args[64]; 264 // We don't know a better way to forward ... into REAL function. We can 265 // increase args size if neccecary. 266 CHECK_LE(argc, ARRAY_SIZE(args)); 267 internal_memset(args, 0, sizeof(args)); 268 va_start(ap, argc); 269 for (int i = 0; i < argc; ++i) args[i] = va_arg(ap, uptr); 270 va_end(ap); 271 272# define ENUMERATE_ARRAY_4(start) \ 273 args[start], args[start + 1], args[start + 2], args[start + 3] 274# define ENUMERATE_ARRAY_16(start) \ 275 ENUMERATE_ARRAY_4(start), ENUMERATE_ARRAY_4(start + 4), \ 276 ENUMERATE_ARRAY_4(start + 8), ENUMERATE_ARRAY_4(start + 12) 277# define ENUMERATE_ARRAY_64() \ 278 ENUMERATE_ARRAY_16(0), ENUMERATE_ARRAY_16(16), ENUMERATE_ARRAY_16(32), \ 279 ENUMERATE_ARRAY_16(48) 280 281 REAL(makecontext) 282 ((struct ucontext_t *)ucp, func, argc, ENUMERATE_ARRAY_64()); 283 284# undef ENUMERATE_ARRAY_4 285# undef ENUMERATE_ARRAY_16 286# undef ENUMERATE_ARRAY_64 287 288 // Sign the stack so we can identify it for unpoisoning. 289 SignContextStack(ucp); 290} 291 292INTERCEPTOR(int, swapcontext, struct ucontext_t *oucp, 293 struct ucontext_t *ucp) { 294 static bool reported_warning = false; 295 if (!reported_warning) { 296 Report("WARNING: ASan doesn't fully support makecontext/swapcontext " 297 "functions and may produce false positives in some cases!\n"); 298 reported_warning = true; 299 } 300 // Clear shadow memory for new context (it may share stack 301 // with current context). 302 uptr stack, ssize; 303 ReadContextStack(ucp, &stack, &ssize); 304 ClearShadowMemoryForContextStack(stack, ssize); 305 306# if __has_attribute(__indirect_return__) && \ 307 (defined(__x86_64__) || defined(__i386__)) 308 int (*real_swapcontext)(struct ucontext_t *, struct ucontext_t *) 309 __attribute__((__indirect_return__)) = REAL(swapcontext); 310 int res = real_swapcontext(oucp, ucp); 311# else 312 int res = REAL(swapcontext)(oucp, ucp); 313# endif 314 // swapcontext technically does not return, but program may swap context to 315 // "oucp" later, that would look as if swapcontext() returned 0. 316 // We need to clear shadow for ucp once again, as it may be in arbitrary 317 // state. 318 ClearShadowMemoryForContextStack(stack, ssize); 319 return res; 320} 321#endif // ASAN_INTERCEPT_SWAPCONTEXT 322 323#if SANITIZER_NETBSD 324#define longjmp __longjmp14 325#define siglongjmp __siglongjmp14 326#endif 327 328INTERCEPTOR(void, longjmp, void *env, int val) { 329 __asan_handle_no_return(); 330 REAL(longjmp)(env, val); 331} 332 333#if ASAN_INTERCEPT__LONGJMP 334INTERCEPTOR(void, _longjmp, void *env, int val) { 335 __asan_handle_no_return(); 336 REAL(_longjmp)(env, val); 337} 338#endif 339 340#if ASAN_INTERCEPT___LONGJMP_CHK 341INTERCEPTOR(void, __longjmp_chk, void *env, int val) { 342 __asan_handle_no_return(); 343 REAL(__longjmp_chk)(env, val); 344} 345#endif 346 347#if ASAN_INTERCEPT_SIGLONGJMP 348INTERCEPTOR(void, siglongjmp, void *env, int val) { 349 __asan_handle_no_return(); 350 REAL(siglongjmp)(env, val); 351} 352#endif 353 354#if ASAN_INTERCEPT___CXA_THROW 355INTERCEPTOR(void, __cxa_throw, void *a, void *b, void *c) { 356 CHECK(REAL(__cxa_throw)); 357 __asan_handle_no_return(); 358 REAL(__cxa_throw)(a, b, c); 359} 360#endif 361 362#if ASAN_INTERCEPT___CXA_RETHROW_PRIMARY_EXCEPTION 363INTERCEPTOR(void, __cxa_rethrow_primary_exception, void *a) { 364 CHECK(REAL(__cxa_rethrow_primary_exception)); 365 __asan_handle_no_return(); 366 REAL(__cxa_rethrow_primary_exception)(a); 367} 368#endif 369 370#if ASAN_INTERCEPT__UNWIND_RAISEEXCEPTION 371INTERCEPTOR(_Unwind_Reason_Code, _Unwind_RaiseException, 372 _Unwind_Exception *object) { 373 CHECK(REAL(_Unwind_RaiseException)); 374 __asan_handle_no_return(); 375 return REAL(_Unwind_RaiseException)(object); 376} 377#endif 378 379#if ASAN_INTERCEPT__SJLJ_UNWIND_RAISEEXCEPTION 380INTERCEPTOR(_Unwind_Reason_Code, _Unwind_SjLj_RaiseException, 381 _Unwind_Exception *object) { 382 CHECK(REAL(_Unwind_SjLj_RaiseException)); 383 __asan_handle_no_return(); 384 return REAL(_Unwind_SjLj_RaiseException)(object); 385} 386#endif 387 388#if ASAN_INTERCEPT_INDEX 389# if ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX 390INTERCEPTOR(char*, index, const char *string, int c) 391 ALIAS(WRAPPER_NAME(strchr)); 392# else 393# if SANITIZER_APPLE 394DECLARE_REAL(char*, index, const char *string, int c) 395OVERRIDE_FUNCTION(index, strchr); 396# else 397DEFINE_REAL(char*, index, const char *string, int c) 398# endif 399# endif 400#endif // ASAN_INTERCEPT_INDEX 401 402// For both strcat() and strncat() we need to check the validity of |to| 403// argument irrespective of the |from| length. 404 INTERCEPTOR(char *, strcat, char *to, const char *from) { 405 void *ctx; 406 ASAN_INTERCEPTOR_ENTER(ctx, strcat); 407 ENSURE_ASAN_INITED(); 408 if (flags()->replace_str) { 409 uptr from_length = internal_strlen(from); 410 ASAN_READ_RANGE(ctx, from, from_length + 1); 411 uptr to_length = internal_strlen(to); 412 ASAN_READ_STRING_OF_LEN(ctx, to, to_length, to_length); 413 ASAN_WRITE_RANGE(ctx, to + to_length, from_length + 1); 414 // If the copying actually happens, the |from| string should not overlap 415 // with the resulting string starting at |to|, which has a length of 416 // to_length + from_length + 1. 417 if (from_length > 0) { 418 CHECK_RANGES_OVERLAP("strcat", to, from_length + to_length + 1, from, 419 from_length + 1); 420 } 421 } 422 return REAL(strcat)(to, from); 423 } 424 425INTERCEPTOR(char*, strncat, char *to, const char *from, uptr size) { 426 void *ctx; 427 ASAN_INTERCEPTOR_ENTER(ctx, strncat); 428 ENSURE_ASAN_INITED(); 429 if (flags()->replace_str) { 430 uptr from_length = MaybeRealStrnlen(from, size); 431 uptr copy_length = Min(size, from_length + 1); 432 ASAN_READ_RANGE(ctx, from, copy_length); 433 uptr to_length = internal_strlen(to); 434 ASAN_READ_STRING_OF_LEN(ctx, to, to_length, to_length); 435 ASAN_WRITE_RANGE(ctx, to + to_length, from_length + 1); 436 if (from_length > 0) { 437 CHECK_RANGES_OVERLAP("strncat", to, to_length + copy_length + 1, 438 from, copy_length); 439 } 440 } 441 return REAL(strncat)(to, from, size); 442} 443 444INTERCEPTOR(char *, strcpy, char *to, const char *from) { 445 void *ctx; 446 ASAN_INTERCEPTOR_ENTER(ctx, strcpy); 447#if SANITIZER_APPLE 448 if (UNLIKELY(!asan_inited)) 449 return REAL(strcpy)(to, from); 450#endif 451 // strcpy is called from malloc_default_purgeable_zone() 452 // in __asan::ReplaceSystemAlloc() on Mac. 453 if (asan_init_is_running) { 454 return REAL(strcpy)(to, from); 455 } 456 ENSURE_ASAN_INITED(); 457 if (flags()->replace_str) { 458 uptr from_size = internal_strlen(from) + 1; 459 CHECK_RANGES_OVERLAP("strcpy", to, from_size, from, from_size); 460 ASAN_READ_RANGE(ctx, from, from_size); 461 ASAN_WRITE_RANGE(ctx, to, from_size); 462 } 463 return REAL(strcpy)(to, from); 464} 465 466INTERCEPTOR(char*, strdup, const char *s) { 467 void *ctx; 468 ASAN_INTERCEPTOR_ENTER(ctx, strdup); 469 if (UNLIKELY(!asan_inited)) return internal_strdup(s); 470 ENSURE_ASAN_INITED(); 471 uptr length = internal_strlen(s); 472 if (flags()->replace_str) { 473 ASAN_READ_RANGE(ctx, s, length + 1); 474 } 475 GET_STACK_TRACE_MALLOC; 476 void *new_mem = asan_malloc(length + 1, &stack); 477 REAL(memcpy)(new_mem, s, length + 1); 478 return reinterpret_cast<char*>(new_mem); 479} 480 481#if ASAN_INTERCEPT___STRDUP 482INTERCEPTOR(char*, __strdup, const char *s) { 483 void *ctx; 484 ASAN_INTERCEPTOR_ENTER(ctx, strdup); 485 if (UNLIKELY(!asan_inited)) return internal_strdup(s); 486 ENSURE_ASAN_INITED(); 487 uptr length = internal_strlen(s); 488 if (flags()->replace_str) { 489 ASAN_READ_RANGE(ctx, s, length + 1); 490 } 491 GET_STACK_TRACE_MALLOC; 492 void *new_mem = asan_malloc(length + 1, &stack); 493 REAL(memcpy)(new_mem, s, length + 1); 494 return reinterpret_cast<char*>(new_mem); 495} 496#endif // ASAN_INTERCEPT___STRDUP 497 498INTERCEPTOR(char*, strncpy, char *to, const char *from, uptr size) { 499 void *ctx; 500 ASAN_INTERCEPTOR_ENTER(ctx, strncpy); 501 ENSURE_ASAN_INITED(); 502 if (flags()->replace_str) { 503 uptr from_size = Min(size, MaybeRealStrnlen(from, size) + 1); 504 CHECK_RANGES_OVERLAP("strncpy", to, from_size, from, from_size); 505 ASAN_READ_RANGE(ctx, from, from_size); 506 ASAN_WRITE_RANGE(ctx, to, size); 507 } 508 return REAL(strncpy)(to, from, size); 509} 510 511INTERCEPTOR(long, strtol, const char *nptr, char **endptr, int base) { 512 void *ctx; 513 ASAN_INTERCEPTOR_ENTER(ctx, strtol); 514 ENSURE_ASAN_INITED(); 515 if (!flags()->replace_str) { 516 return REAL(strtol)(nptr, endptr, base); 517 } 518 char *real_endptr; 519 long result = REAL(strtol)(nptr, &real_endptr, base); 520 StrtolFixAndCheck(ctx, nptr, endptr, real_endptr, base); 521 return result; 522} 523 524INTERCEPTOR(int, atoi, const char *nptr) { 525 void *ctx; 526 ASAN_INTERCEPTOR_ENTER(ctx, atoi); 527#if SANITIZER_APPLE 528 if (UNLIKELY(!asan_inited)) return REAL(atoi)(nptr); 529#endif 530 ENSURE_ASAN_INITED(); 531 if (!flags()->replace_str) { 532 return REAL(atoi)(nptr); 533 } 534 char *real_endptr; 535 // "man atoi" tells that behavior of atoi(nptr) is the same as 536 // strtol(nptr, 0, 10), i.e. it sets errno to ERANGE if the 537 // parsed integer can't be stored in *long* type (even if it's 538 // different from int). So, we just imitate this behavior. 539 int result = REAL(strtol)(nptr, &real_endptr, 10); 540 FixRealStrtolEndptr(nptr, &real_endptr); 541 ASAN_READ_STRING(ctx, nptr, (real_endptr - nptr) + 1); 542 return result; 543} 544 545INTERCEPTOR(long, atol, const char *nptr) { 546 void *ctx; 547 ASAN_INTERCEPTOR_ENTER(ctx, atol); 548#if SANITIZER_APPLE 549 if (UNLIKELY(!asan_inited)) return REAL(atol)(nptr); 550#endif 551 ENSURE_ASAN_INITED(); 552 if (!flags()->replace_str) { 553 return REAL(atol)(nptr); 554 } 555 char *real_endptr; 556 long result = REAL(strtol)(nptr, &real_endptr, 10); 557 FixRealStrtolEndptr(nptr, &real_endptr); 558 ASAN_READ_STRING(ctx, nptr, (real_endptr - nptr) + 1); 559 return result; 560} 561 562#if ASAN_INTERCEPT_ATOLL_AND_STRTOLL 563INTERCEPTOR(long long, strtoll, const char *nptr, char **endptr, int base) { 564 void *ctx; 565 ASAN_INTERCEPTOR_ENTER(ctx, strtoll); 566 ENSURE_ASAN_INITED(); 567 if (!flags()->replace_str) { 568 return REAL(strtoll)(nptr, endptr, base); 569 } 570 char *real_endptr; 571 long long result = REAL(strtoll)(nptr, &real_endptr, base); 572 StrtolFixAndCheck(ctx, nptr, endptr, real_endptr, base); 573 return result; 574} 575 576INTERCEPTOR(long long, atoll, const char *nptr) { 577 void *ctx; 578 ASAN_INTERCEPTOR_ENTER(ctx, atoll); 579 ENSURE_ASAN_INITED(); 580 if (!flags()->replace_str) { 581 return REAL(atoll)(nptr); 582 } 583 char *real_endptr; 584 long long result = REAL(strtoll)(nptr, &real_endptr, 10); 585 FixRealStrtolEndptr(nptr, &real_endptr); 586 ASAN_READ_STRING(ctx, nptr, (real_endptr - nptr) + 1); 587 return result; 588} 589#endif // ASAN_INTERCEPT_ATOLL_AND_STRTOLL 590 591#if ASAN_INTERCEPT___CXA_ATEXIT || ASAN_INTERCEPT_ATEXIT 592static void AtCxaAtexit(void *unused) { 593 (void)unused; 594 StopInitOrderChecking(); 595} 596#endif 597 598#if ASAN_INTERCEPT___CXA_ATEXIT 599INTERCEPTOR(int, __cxa_atexit, void (*func)(void *), void *arg, 600 void *dso_handle) { 601#if SANITIZER_APPLE 602 if (UNLIKELY(!asan_inited)) return REAL(__cxa_atexit)(func, arg, dso_handle); 603#endif 604 ENSURE_ASAN_INITED(); 605#if CAN_SANITIZE_LEAKS 606 __lsan::ScopedInterceptorDisabler disabler; 607#endif 608 int res = REAL(__cxa_atexit)(func, arg, dso_handle); 609 REAL(__cxa_atexit)(AtCxaAtexit, nullptr, nullptr); 610 return res; 611} 612#endif // ASAN_INTERCEPT___CXA_ATEXIT 613 614#if ASAN_INTERCEPT_ATEXIT 615INTERCEPTOR(int, atexit, void (*func)()) { 616 ENSURE_ASAN_INITED(); 617#if CAN_SANITIZE_LEAKS 618 __lsan::ScopedInterceptorDisabler disabler; 619#endif 620 // Avoid calling real atexit as it is unreachable on at least on Linux. 621 int res = REAL(__cxa_atexit)((void (*)(void *a))func, nullptr, nullptr); 622 REAL(__cxa_atexit)(AtCxaAtexit, nullptr, nullptr); 623 return res; 624} 625#endif 626 627#if ASAN_INTERCEPT_PTHREAD_ATFORK 628extern "C" { 629extern int _pthread_atfork(void (*prepare)(), void (*parent)(), 630 void (*child)()); 631}; 632 633INTERCEPTOR(int, pthread_atfork, void (*prepare)(), void (*parent)(), 634 void (*child)()) { 635#if CAN_SANITIZE_LEAKS 636 __lsan::ScopedInterceptorDisabler disabler; 637#endif 638 // REAL(pthread_atfork) cannot be called due to symbol indirections at least 639 // on NetBSD 640 return _pthread_atfork(prepare, parent, child); 641} 642#endif 643 644#if ASAN_INTERCEPT_VFORK 645DEFINE_REAL(int, vfork) 646DECLARE_EXTERN_INTERCEPTOR_AND_WRAPPER(int, vfork) 647#endif 648 649// ---------------------- InitializeAsanInterceptors ---------------- {{{1 650namespace __asan { 651void InitializeAsanInterceptors() { 652 static bool was_called_once; 653 CHECK(!was_called_once); 654 was_called_once = true; 655 InitializeCommonInterceptors(); 656 InitializeSignalInterceptors(); 657 658 // Intercept str* functions. 659 ASAN_INTERCEPT_FUNC(strcat); 660 ASAN_INTERCEPT_FUNC(strcpy); 661 ASAN_INTERCEPT_FUNC(strncat); 662 ASAN_INTERCEPT_FUNC(strncpy); 663 ASAN_INTERCEPT_FUNC(strdup); 664#if ASAN_INTERCEPT___STRDUP 665 ASAN_INTERCEPT_FUNC(__strdup); 666#endif 667#if ASAN_INTERCEPT_INDEX && ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX 668 ASAN_INTERCEPT_FUNC(index); 669#endif 670 671 ASAN_INTERCEPT_FUNC(atoi); 672 ASAN_INTERCEPT_FUNC(atol); 673 ASAN_INTERCEPT_FUNC(strtol); 674#if ASAN_INTERCEPT_ATOLL_AND_STRTOLL 675 ASAN_INTERCEPT_FUNC(atoll); 676 ASAN_INTERCEPT_FUNC(strtoll); 677#endif 678 679 // Intecept jump-related functions. 680 ASAN_INTERCEPT_FUNC(longjmp); 681 682# if ASAN_INTERCEPT_SWAPCONTEXT 683 ASAN_INTERCEPT_FUNC(swapcontext); 684 ASAN_INTERCEPT_FUNC(makecontext); 685# endif 686# if ASAN_INTERCEPT__LONGJMP 687 ASAN_INTERCEPT_FUNC(_longjmp); 688#endif 689#if ASAN_INTERCEPT___LONGJMP_CHK 690 ASAN_INTERCEPT_FUNC(__longjmp_chk); 691#endif 692#if ASAN_INTERCEPT_SIGLONGJMP 693 ASAN_INTERCEPT_FUNC(siglongjmp); 694#endif 695 696 // Intercept exception handling functions. 697#if ASAN_INTERCEPT___CXA_THROW 698 ASAN_INTERCEPT_FUNC(__cxa_throw); 699#endif 700#if ASAN_INTERCEPT___CXA_RETHROW_PRIMARY_EXCEPTION 701 ASAN_INTERCEPT_FUNC(__cxa_rethrow_primary_exception); 702#endif 703 // Indirectly intercept std::rethrow_exception. 704#if ASAN_INTERCEPT__UNWIND_RAISEEXCEPTION 705 INTERCEPT_FUNCTION(_Unwind_RaiseException); 706#endif 707 // Indirectly intercept std::rethrow_exception. 708#if ASAN_INTERCEPT__UNWIND_SJLJ_RAISEEXCEPTION 709 INTERCEPT_FUNCTION(_Unwind_SjLj_RaiseException); 710#endif 711 712 // Intercept threading-related functions 713#if ASAN_INTERCEPT_PTHREAD_CREATE 714// TODO: this should probably have an unversioned fallback for newer arches? 715#if defined(ASAN_PTHREAD_CREATE_VERSION) 716 ASAN_INTERCEPT_FUNC_VER(pthread_create, ASAN_PTHREAD_CREATE_VERSION); 717#else 718 ASAN_INTERCEPT_FUNC(pthread_create); 719#endif 720 ASAN_INTERCEPT_FUNC(pthread_join); 721#endif 722 723 // Intercept atexit function. 724#if ASAN_INTERCEPT___CXA_ATEXIT 725 ASAN_INTERCEPT_FUNC(__cxa_atexit); 726#endif 727 728#if ASAN_INTERCEPT_ATEXIT 729 ASAN_INTERCEPT_FUNC(atexit); 730#endif 731 732#if ASAN_INTERCEPT_PTHREAD_ATFORK 733 ASAN_INTERCEPT_FUNC(pthread_atfork); 734#endif 735 736#if ASAN_INTERCEPT_VFORK 737 ASAN_INTERCEPT_FUNC(vfork); 738#endif 739 740 InitializePlatformInterceptors(); 741 742 VReport(1, "AddressSanitizer: libc interceptors initialized\n"); 743} 744 745} // namespace __asan 746 747#endif // !SANITIZER_FUCHSIA 748