168d75effSDimitry Andric //===-- asan_interceptors.cpp ---------------------------------------------===// 268d75effSDimitry Andric // 368d75effSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 468d75effSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 568d75effSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 668d75effSDimitry Andric // 768d75effSDimitry Andric //===----------------------------------------------------------------------===// 868d75effSDimitry Andric // 968d75effSDimitry Andric // This file is a part of AddressSanitizer, an address sanity checker. 1068d75effSDimitry Andric // 1168d75effSDimitry Andric // Intercept various libc functions. 1268d75effSDimitry Andric //===----------------------------------------------------------------------===// 1368d75effSDimitry Andric 1468d75effSDimitry Andric #include "asan_interceptors.h" 1568d75effSDimitry Andric #include "asan_allocator.h" 1668d75effSDimitry Andric #include "asan_internal.h" 1768d75effSDimitry Andric #include "asan_mapping.h" 1868d75effSDimitry Andric #include "asan_poisoning.h" 1968d75effSDimitry Andric #include "asan_report.h" 2068d75effSDimitry Andric #include "asan_stack.h" 2168d75effSDimitry Andric #include "asan_stats.h" 2268d75effSDimitry Andric #include "asan_suppressions.h" 2368d75effSDimitry Andric #include "lsan/lsan_common.h" 2468d75effSDimitry Andric #include "sanitizer_common/sanitizer_libc.h" 2568d75effSDimitry Andric 2668d75effSDimitry Andric // There is no general interception at all on Fuchsia and RTEMS. 2768d75effSDimitry Andric // Only the functions in asan_interceptors_memintrinsics.cpp are 2868d75effSDimitry Andric // really defined to replace libc functions. 2968d75effSDimitry Andric #if !SANITIZER_FUCHSIA && !SANITIZER_RTEMS 3068d75effSDimitry Andric 3168d75effSDimitry Andric #if SANITIZER_POSIX 3268d75effSDimitry Andric #include "sanitizer_common/sanitizer_posix.h" 3368d75effSDimitry Andric #endif 3468d75effSDimitry Andric 3568d75effSDimitry Andric #if ASAN_INTERCEPT__UNWIND_RAISEEXCEPTION || \ 3668d75effSDimitry Andric ASAN_INTERCEPT__SJLJ_UNWIND_RAISEEXCEPTION 3768d75effSDimitry Andric #include <unwind.h> 3868d75effSDimitry Andric #endif 3968d75effSDimitry Andric 4068d75effSDimitry Andric #if defined(__i386) && SANITIZER_LINUX 4168d75effSDimitry Andric #define ASAN_PTHREAD_CREATE_VERSION "GLIBC_2.1" 4268d75effSDimitry Andric #elif defined(__mips__) && SANITIZER_LINUX 4368d75effSDimitry Andric #define ASAN_PTHREAD_CREATE_VERSION "GLIBC_2.2" 4468d75effSDimitry Andric #endif 4568d75effSDimitry Andric 4668d75effSDimitry Andric namespace __asan { 4768d75effSDimitry Andric 4868d75effSDimitry Andric #define ASAN_READ_STRING_OF_LEN(ctx, s, len, n) \ 4968d75effSDimitry Andric ASAN_READ_RANGE((ctx), (s), \ 5068d75effSDimitry Andric common_flags()->strict_string_checks ? (len) + 1 : (n)) 5168d75effSDimitry Andric 5268d75effSDimitry Andric #define ASAN_READ_STRING(ctx, s, n) \ 5368d75effSDimitry Andric ASAN_READ_STRING_OF_LEN((ctx), (s), REAL(strlen)(s), (n)) 5468d75effSDimitry Andric 5568d75effSDimitry Andric static inline uptr MaybeRealStrnlen(const char *s, uptr maxlen) { 5668d75effSDimitry Andric #if SANITIZER_INTERCEPT_STRNLEN 5768d75effSDimitry Andric if (REAL(strnlen)) { 5868d75effSDimitry Andric return REAL(strnlen)(s, maxlen); 5968d75effSDimitry Andric } 6068d75effSDimitry Andric #endif 6168d75effSDimitry Andric return internal_strnlen(s, maxlen); 6268d75effSDimitry Andric } 6368d75effSDimitry Andric 6468d75effSDimitry Andric void SetThreadName(const char *name) { 6568d75effSDimitry Andric AsanThread *t = GetCurrentThread(); 6668d75effSDimitry Andric if (t) 6768d75effSDimitry Andric asanThreadRegistry().SetThreadName(t->tid(), name); 6868d75effSDimitry Andric } 6968d75effSDimitry Andric 7068d75effSDimitry Andric int OnExit() { 7168d75effSDimitry Andric if (CAN_SANITIZE_LEAKS && common_flags()->detect_leaks && 7268d75effSDimitry Andric __lsan::HasReportedLeaks()) { 7368d75effSDimitry Andric return common_flags()->exitcode; 7468d75effSDimitry Andric } 7568d75effSDimitry Andric // FIXME: ask frontend whether we need to return failure. 7668d75effSDimitry Andric return 0; 7768d75effSDimitry Andric } 7868d75effSDimitry Andric 7968d75effSDimitry Andric } // namespace __asan 8068d75effSDimitry Andric 8168d75effSDimitry Andric // ---------------------- Wrappers ---------------- {{{1 8268d75effSDimitry Andric using namespace __asan; 8368d75effSDimitry Andric 8468d75effSDimitry Andric DECLARE_REAL_AND_INTERCEPTOR(void *, malloc, uptr) 8568d75effSDimitry Andric DECLARE_REAL_AND_INTERCEPTOR(void, free, void *) 8668d75effSDimitry Andric 8768d75effSDimitry Andric #define ASAN_INTERCEPTOR_ENTER(ctx, func) \ 8868d75effSDimitry Andric AsanInterceptorContext _ctx = {#func}; \ 8968d75effSDimitry Andric ctx = (void *)&_ctx; \ 9068d75effSDimitry Andric (void) ctx; \ 9168d75effSDimitry Andric 9268d75effSDimitry Andric #define COMMON_INTERCEPT_FUNCTION(name) ASAN_INTERCEPT_FUNC(name) 9368d75effSDimitry Andric #define COMMON_INTERCEPT_FUNCTION_VER(name, ver) \ 9468d75effSDimitry Andric ASAN_INTERCEPT_FUNC_VER(name, ver) 9568d75effSDimitry Andric #define COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, size) \ 9668d75effSDimitry Andric ASAN_WRITE_RANGE(ctx, ptr, size) 9768d75effSDimitry Andric #define COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, size) \ 9868d75effSDimitry Andric ASAN_READ_RANGE(ctx, ptr, size) 9968d75effSDimitry Andric #define COMMON_INTERCEPTOR_ENTER(ctx, func, ...) \ 10068d75effSDimitry Andric ASAN_INTERCEPTOR_ENTER(ctx, func); \ 10168d75effSDimitry Andric do { \ 10268d75effSDimitry Andric if (asan_init_is_running) \ 10368d75effSDimitry Andric return REAL(func)(__VA_ARGS__); \ 10468d75effSDimitry Andric if (SANITIZER_MAC && UNLIKELY(!asan_inited)) \ 10568d75effSDimitry Andric return REAL(func)(__VA_ARGS__); \ 10668d75effSDimitry Andric ENSURE_ASAN_INITED(); \ 10768d75effSDimitry Andric } while (false) 10868d75effSDimitry Andric #define COMMON_INTERCEPTOR_DIR_ACQUIRE(ctx, path) \ 10968d75effSDimitry Andric do { \ 11068d75effSDimitry Andric } while (false) 11168d75effSDimitry Andric #define COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd) \ 11268d75effSDimitry Andric do { \ 11368d75effSDimitry Andric } while (false) 11468d75effSDimitry Andric #define COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd) \ 11568d75effSDimitry Andric do { \ 11668d75effSDimitry Andric } while (false) 11768d75effSDimitry Andric #define COMMON_INTERCEPTOR_FD_SOCKET_ACCEPT(ctx, fd, newfd) \ 11868d75effSDimitry Andric do { \ 11968d75effSDimitry Andric } while (false) 12068d75effSDimitry Andric #define COMMON_INTERCEPTOR_SET_THREAD_NAME(ctx, name) SetThreadName(name) 12168d75effSDimitry Andric // Should be asanThreadRegistry().SetThreadNameByUserId(thread, name) 12268d75effSDimitry Andric // But asan does not remember UserId's for threads (pthread_t); 12368d75effSDimitry Andric // and remembers all ever existed threads, so the linear search by UserId 12468d75effSDimitry Andric // can be slow. 12568d75effSDimitry Andric #define COMMON_INTERCEPTOR_SET_PTHREAD_NAME(ctx, thread, name) \ 12668d75effSDimitry Andric do { \ 12768d75effSDimitry Andric } while (false) 12868d75effSDimitry Andric #define COMMON_INTERCEPTOR_BLOCK_REAL(name) REAL(name) 12968d75effSDimitry Andric // Strict init-order checking is dlopen-hostile: 13068d75effSDimitry Andric // https://github.com/google/sanitizers/issues/178 13168d75effSDimitry Andric #define COMMON_INTERCEPTOR_ON_DLOPEN(filename, flag) \ 13268d75effSDimitry Andric do { \ 13368d75effSDimitry Andric if (flags()->strict_init_order) \ 13468d75effSDimitry Andric StopInitOrderChecking(); \ 13568d75effSDimitry Andric CheckNoDeepBind(filename, flag); \ 13668d75effSDimitry Andric } while (false) 13768d75effSDimitry Andric #define COMMON_INTERCEPTOR_ON_EXIT(ctx) OnExit() 13868d75effSDimitry Andric #define COMMON_INTERCEPTOR_LIBRARY_LOADED(filename, handle) 13968d75effSDimitry Andric #define COMMON_INTERCEPTOR_LIBRARY_UNLOADED() 14068d75effSDimitry Andric #define COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED (!asan_inited) 14168d75effSDimitry Andric #define COMMON_INTERCEPTOR_GET_TLS_RANGE(begin, end) \ 14268d75effSDimitry Andric if (AsanThread *t = GetCurrentThread()) { \ 14368d75effSDimitry Andric *begin = t->tls_begin(); \ 14468d75effSDimitry Andric *end = t->tls_end(); \ 14568d75effSDimitry Andric } else { \ 14668d75effSDimitry Andric *begin = *end = 0; \ 14768d75effSDimitry Andric } 14868d75effSDimitry Andric 14968d75effSDimitry Andric #define COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, to, from, size) \ 15068d75effSDimitry Andric do { \ 15168d75effSDimitry Andric ASAN_INTERCEPTOR_ENTER(ctx, memmove); \ 15268d75effSDimitry Andric ASAN_MEMMOVE_IMPL(ctx, to, from, size); \ 15368d75effSDimitry Andric } while (false) 15468d75effSDimitry Andric 15568d75effSDimitry Andric #define COMMON_INTERCEPTOR_MEMCPY_IMPL(ctx, to, from, size) \ 15668d75effSDimitry Andric do { \ 15768d75effSDimitry Andric ASAN_INTERCEPTOR_ENTER(ctx, memcpy); \ 15868d75effSDimitry Andric ASAN_MEMCPY_IMPL(ctx, to, from, size); \ 15968d75effSDimitry Andric } while (false) 16068d75effSDimitry Andric 16168d75effSDimitry Andric #define COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, c, size) \ 16268d75effSDimitry Andric do { \ 16368d75effSDimitry Andric ASAN_INTERCEPTOR_ENTER(ctx, memset); \ 16468d75effSDimitry Andric ASAN_MEMSET_IMPL(ctx, block, c, size); \ 16568d75effSDimitry Andric } while (false) 16668d75effSDimitry Andric 16768d75effSDimitry Andric #if CAN_SANITIZE_LEAKS 16868d75effSDimitry Andric #define COMMON_INTERCEPTOR_STRERROR() \ 16968d75effSDimitry Andric __lsan::ScopedInterceptorDisabler disabler 17068d75effSDimitry Andric #endif 17168d75effSDimitry Andric 17268d75effSDimitry Andric #include "sanitizer_common/sanitizer_common_interceptors.inc" 17368d75effSDimitry Andric #include "sanitizer_common/sanitizer_signal_interceptors.inc" 17468d75effSDimitry Andric 17568d75effSDimitry Andric // Syscall interceptors don't have contexts, we don't support suppressions 17668d75effSDimitry Andric // for them. 17768d75effSDimitry Andric #define COMMON_SYSCALL_PRE_READ_RANGE(p, s) ASAN_READ_RANGE(nullptr, p, s) 17868d75effSDimitry Andric #define COMMON_SYSCALL_PRE_WRITE_RANGE(p, s) ASAN_WRITE_RANGE(nullptr, p, s) 17968d75effSDimitry Andric #define COMMON_SYSCALL_POST_READ_RANGE(p, s) \ 18068d75effSDimitry Andric do { \ 18168d75effSDimitry Andric (void)(p); \ 18268d75effSDimitry Andric (void)(s); \ 18368d75effSDimitry Andric } while (false) 18468d75effSDimitry Andric #define COMMON_SYSCALL_POST_WRITE_RANGE(p, s) \ 18568d75effSDimitry Andric do { \ 18668d75effSDimitry Andric (void)(p); \ 18768d75effSDimitry Andric (void)(s); \ 18868d75effSDimitry Andric } while (false) 18968d75effSDimitry Andric #include "sanitizer_common/sanitizer_common_syscalls.inc" 19068d75effSDimitry Andric #include "sanitizer_common/sanitizer_syscalls_netbsd.inc" 19168d75effSDimitry Andric 19268d75effSDimitry Andric #if ASAN_INTERCEPT_PTHREAD_CREATE 19368d75effSDimitry Andric static thread_return_t THREAD_CALLING_CONV asan_thread_start(void *arg) { 194*e8d8bef9SDimitry Andric AsanThread *t = (AsanThread *)arg; 19568d75effSDimitry Andric SetCurrentThread(t); 196*e8d8bef9SDimitry Andric return t->ThreadStart(GetTid()); 19768d75effSDimitry Andric } 19868d75effSDimitry Andric 19968d75effSDimitry Andric INTERCEPTOR(int, pthread_create, void *thread, 20068d75effSDimitry Andric void *attr, void *(*start_routine)(void*), void *arg) { 20168d75effSDimitry Andric EnsureMainThreadIDIsCorrect(); 20268d75effSDimitry Andric // Strict init-order checking is thread-hostile. 20368d75effSDimitry Andric if (flags()->strict_init_order) 20468d75effSDimitry Andric StopInitOrderChecking(); 20568d75effSDimitry Andric GET_STACK_TRACE_THREAD; 20668d75effSDimitry Andric int detached = 0; 20768d75effSDimitry Andric if (attr) 20868d75effSDimitry Andric REAL(pthread_attr_getdetachstate)(attr, &detached); 209*e8d8bef9SDimitry Andric 210*e8d8bef9SDimitry Andric u32 current_tid = GetCurrentTidOrInvalid(); 211*e8d8bef9SDimitry Andric AsanThread *t = 212*e8d8bef9SDimitry Andric AsanThread::Create(start_routine, arg, current_tid, &stack, detached); 213*e8d8bef9SDimitry Andric 21468d75effSDimitry Andric int result; 21568d75effSDimitry Andric { 21668d75effSDimitry Andric // Ignore all allocations made by pthread_create: thread stack/TLS may be 21768d75effSDimitry Andric // stored by pthread for future reuse even after thread destruction, and 21868d75effSDimitry Andric // the linked list it's stored in doesn't even hold valid pointers to the 21968d75effSDimitry Andric // objects, the latter are calculated by obscure pointer arithmetic. 22068d75effSDimitry Andric #if CAN_SANITIZE_LEAKS 22168d75effSDimitry Andric __lsan::ScopedInterceptorDisabler disabler; 22268d75effSDimitry Andric #endif 223*e8d8bef9SDimitry Andric result = REAL(pthread_create)(thread, attr, asan_thread_start, t); 22468d75effSDimitry Andric } 225*e8d8bef9SDimitry Andric if (result != 0) { 226*e8d8bef9SDimitry Andric // If the thread didn't start delete the AsanThread to avoid leaking it. 227*e8d8bef9SDimitry Andric // Note AsanThreadContexts never get destroyed so the AsanThreadContext 228*e8d8bef9SDimitry Andric // that was just created for the AsanThread is wasted. 229*e8d8bef9SDimitry Andric t->Destroy(); 23068d75effSDimitry Andric } 23168d75effSDimitry Andric return result; 23268d75effSDimitry Andric } 23368d75effSDimitry Andric 23468d75effSDimitry Andric INTERCEPTOR(int, pthread_join, void *t, void **arg) { 23568d75effSDimitry Andric return real_pthread_join(t, arg); 23668d75effSDimitry Andric } 23768d75effSDimitry Andric 23868d75effSDimitry Andric DEFINE_REAL_PTHREAD_FUNCTIONS 23968d75effSDimitry Andric #endif // ASAN_INTERCEPT_PTHREAD_CREATE 24068d75effSDimitry Andric 24168d75effSDimitry Andric #if ASAN_INTERCEPT_SWAPCONTEXT 24268d75effSDimitry Andric static void ClearShadowMemoryForContextStack(uptr stack, uptr ssize) { 24368d75effSDimitry Andric // Align to page size. 24468d75effSDimitry Andric uptr PageSize = GetPageSizeCached(); 24568d75effSDimitry Andric uptr bottom = stack & ~(PageSize - 1); 24668d75effSDimitry Andric ssize += stack - bottom; 24768d75effSDimitry Andric ssize = RoundUpTo(ssize, PageSize); 24868d75effSDimitry Andric static const uptr kMaxSaneContextStackSize = 1 << 22; // 4 Mb 24968d75effSDimitry Andric if (AddrIsInMem(bottom) && ssize && ssize <= kMaxSaneContextStackSize) { 25068d75effSDimitry Andric PoisonShadow(bottom, ssize, 0); 25168d75effSDimitry Andric } 25268d75effSDimitry Andric } 25368d75effSDimitry Andric 25468d75effSDimitry Andric INTERCEPTOR(int, swapcontext, struct ucontext_t *oucp, 25568d75effSDimitry Andric struct ucontext_t *ucp) { 25668d75effSDimitry Andric static bool reported_warning = false; 25768d75effSDimitry Andric if (!reported_warning) { 25868d75effSDimitry Andric Report("WARNING: ASan doesn't fully support makecontext/swapcontext " 25968d75effSDimitry Andric "functions and may produce false positives in some cases!\n"); 26068d75effSDimitry Andric reported_warning = true; 26168d75effSDimitry Andric } 26268d75effSDimitry Andric // Clear shadow memory for new context (it may share stack 26368d75effSDimitry Andric // with current context). 26468d75effSDimitry Andric uptr stack, ssize; 26568d75effSDimitry Andric ReadContextStack(ucp, &stack, &ssize); 26668d75effSDimitry Andric ClearShadowMemoryForContextStack(stack, ssize); 26768d75effSDimitry Andric #if __has_attribute(__indirect_return__) && \ 26868d75effSDimitry Andric (defined(__x86_64__) || defined(__i386__)) 26968d75effSDimitry Andric int (*real_swapcontext)(struct ucontext_t *, struct ucontext_t *) 27068d75effSDimitry Andric __attribute__((__indirect_return__)) 27168d75effSDimitry Andric = REAL(swapcontext); 27268d75effSDimitry Andric int res = real_swapcontext(oucp, ucp); 27368d75effSDimitry Andric #else 27468d75effSDimitry Andric int res = REAL(swapcontext)(oucp, ucp); 27568d75effSDimitry Andric #endif 27668d75effSDimitry Andric // swapcontext technically does not return, but program may swap context to 27768d75effSDimitry Andric // "oucp" later, that would look as if swapcontext() returned 0. 27868d75effSDimitry Andric // We need to clear shadow for ucp once again, as it may be in arbitrary 27968d75effSDimitry Andric // state. 28068d75effSDimitry Andric ClearShadowMemoryForContextStack(stack, ssize); 28168d75effSDimitry Andric return res; 28268d75effSDimitry Andric } 28368d75effSDimitry Andric #endif // ASAN_INTERCEPT_SWAPCONTEXT 28468d75effSDimitry Andric 28568d75effSDimitry Andric #if SANITIZER_NETBSD 28668d75effSDimitry Andric #define longjmp __longjmp14 28768d75effSDimitry Andric #define siglongjmp __siglongjmp14 28868d75effSDimitry Andric #endif 28968d75effSDimitry Andric 29068d75effSDimitry Andric INTERCEPTOR(void, longjmp, void *env, int val) { 29168d75effSDimitry Andric __asan_handle_no_return(); 29268d75effSDimitry Andric REAL(longjmp)(env, val); 29368d75effSDimitry Andric } 29468d75effSDimitry Andric 29568d75effSDimitry Andric #if ASAN_INTERCEPT__LONGJMP 29668d75effSDimitry Andric INTERCEPTOR(void, _longjmp, void *env, int val) { 29768d75effSDimitry Andric __asan_handle_no_return(); 29868d75effSDimitry Andric REAL(_longjmp)(env, val); 29968d75effSDimitry Andric } 30068d75effSDimitry Andric #endif 30168d75effSDimitry Andric 30268d75effSDimitry Andric #if ASAN_INTERCEPT___LONGJMP_CHK 30368d75effSDimitry Andric INTERCEPTOR(void, __longjmp_chk, void *env, int val) { 30468d75effSDimitry Andric __asan_handle_no_return(); 30568d75effSDimitry Andric REAL(__longjmp_chk)(env, val); 30668d75effSDimitry Andric } 30768d75effSDimitry Andric #endif 30868d75effSDimitry Andric 30968d75effSDimitry Andric #if ASAN_INTERCEPT_SIGLONGJMP 31068d75effSDimitry Andric INTERCEPTOR(void, siglongjmp, void *env, int val) { 31168d75effSDimitry Andric __asan_handle_no_return(); 31268d75effSDimitry Andric REAL(siglongjmp)(env, val); 31368d75effSDimitry Andric } 31468d75effSDimitry Andric #endif 31568d75effSDimitry Andric 31668d75effSDimitry Andric #if ASAN_INTERCEPT___CXA_THROW 31768d75effSDimitry Andric INTERCEPTOR(void, __cxa_throw, void *a, void *b, void *c) { 31868d75effSDimitry Andric CHECK(REAL(__cxa_throw)); 31968d75effSDimitry Andric __asan_handle_no_return(); 32068d75effSDimitry Andric REAL(__cxa_throw)(a, b, c); 32168d75effSDimitry Andric } 32268d75effSDimitry Andric #endif 32368d75effSDimitry Andric 32468d75effSDimitry Andric #if ASAN_INTERCEPT___CXA_RETHROW_PRIMARY_EXCEPTION 32568d75effSDimitry Andric INTERCEPTOR(void, __cxa_rethrow_primary_exception, void *a) { 32668d75effSDimitry Andric CHECK(REAL(__cxa_rethrow_primary_exception)); 32768d75effSDimitry Andric __asan_handle_no_return(); 32868d75effSDimitry Andric REAL(__cxa_rethrow_primary_exception)(a); 32968d75effSDimitry Andric } 33068d75effSDimitry Andric #endif 33168d75effSDimitry Andric 33268d75effSDimitry Andric #if ASAN_INTERCEPT__UNWIND_RAISEEXCEPTION 33368d75effSDimitry Andric INTERCEPTOR(_Unwind_Reason_Code, _Unwind_RaiseException, 33468d75effSDimitry Andric _Unwind_Exception *object) { 33568d75effSDimitry Andric CHECK(REAL(_Unwind_RaiseException)); 33668d75effSDimitry Andric __asan_handle_no_return(); 33768d75effSDimitry Andric return REAL(_Unwind_RaiseException)(object); 33868d75effSDimitry Andric } 33968d75effSDimitry Andric #endif 34068d75effSDimitry Andric 34168d75effSDimitry Andric #if ASAN_INTERCEPT__SJLJ_UNWIND_RAISEEXCEPTION 34268d75effSDimitry Andric INTERCEPTOR(_Unwind_Reason_Code, _Unwind_SjLj_RaiseException, 34368d75effSDimitry Andric _Unwind_Exception *object) { 34468d75effSDimitry Andric CHECK(REAL(_Unwind_SjLj_RaiseException)); 34568d75effSDimitry Andric __asan_handle_no_return(); 34668d75effSDimitry Andric return REAL(_Unwind_SjLj_RaiseException)(object); 34768d75effSDimitry Andric } 34868d75effSDimitry Andric #endif 34968d75effSDimitry Andric 35068d75effSDimitry Andric #if ASAN_INTERCEPT_INDEX 35168d75effSDimitry Andric # if ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX 35268d75effSDimitry Andric INTERCEPTOR(char*, index, const char *string, int c) 35368d75effSDimitry Andric ALIAS(WRAPPER_NAME(strchr)); 35468d75effSDimitry Andric # else 35568d75effSDimitry Andric # if SANITIZER_MAC 35668d75effSDimitry Andric DECLARE_REAL(char*, index, const char *string, int c) 35768d75effSDimitry Andric OVERRIDE_FUNCTION(index, strchr); 35868d75effSDimitry Andric # else 35968d75effSDimitry Andric DEFINE_REAL(char*, index, const char *string, int c) 36068d75effSDimitry Andric # endif 36168d75effSDimitry Andric # endif 36268d75effSDimitry Andric #endif // ASAN_INTERCEPT_INDEX 36368d75effSDimitry Andric 36468d75effSDimitry Andric // For both strcat() and strncat() we need to check the validity of |to| 36568d75effSDimitry Andric // argument irrespective of the |from| length. 36668d75effSDimitry Andric INTERCEPTOR(char *, strcat, char *to, const char *from) { 36768d75effSDimitry Andric void *ctx; 36868d75effSDimitry Andric ASAN_INTERCEPTOR_ENTER(ctx, strcat); 36968d75effSDimitry Andric ENSURE_ASAN_INITED(); 37068d75effSDimitry Andric if (flags()->replace_str) { 37168d75effSDimitry Andric uptr from_length = REAL(strlen)(from); 37268d75effSDimitry Andric ASAN_READ_RANGE(ctx, from, from_length + 1); 37368d75effSDimitry Andric uptr to_length = REAL(strlen)(to); 37468d75effSDimitry Andric ASAN_READ_STRING_OF_LEN(ctx, to, to_length, to_length); 37568d75effSDimitry Andric ASAN_WRITE_RANGE(ctx, to + to_length, from_length + 1); 37668d75effSDimitry Andric // If the copying actually happens, the |from| string should not overlap 37768d75effSDimitry Andric // with the resulting string starting at |to|, which has a length of 37868d75effSDimitry Andric // to_length + from_length + 1. 37968d75effSDimitry Andric if (from_length > 0) { 38068d75effSDimitry Andric CHECK_RANGES_OVERLAP("strcat", to, from_length + to_length + 1, from, 38168d75effSDimitry Andric from_length + 1); 38268d75effSDimitry Andric } 38368d75effSDimitry Andric } 38468d75effSDimitry Andric return REAL(strcat)(to, from); 38568d75effSDimitry Andric } 38668d75effSDimitry Andric 38768d75effSDimitry Andric INTERCEPTOR(char*, strncat, char *to, const char *from, uptr size) { 38868d75effSDimitry Andric void *ctx; 38968d75effSDimitry Andric ASAN_INTERCEPTOR_ENTER(ctx, strncat); 39068d75effSDimitry Andric ENSURE_ASAN_INITED(); 39168d75effSDimitry Andric if (flags()->replace_str) { 39268d75effSDimitry Andric uptr from_length = MaybeRealStrnlen(from, size); 39368d75effSDimitry Andric uptr copy_length = Min(size, from_length + 1); 39468d75effSDimitry Andric ASAN_READ_RANGE(ctx, from, copy_length); 39568d75effSDimitry Andric uptr to_length = REAL(strlen)(to); 39668d75effSDimitry Andric ASAN_READ_STRING_OF_LEN(ctx, to, to_length, to_length); 39768d75effSDimitry Andric ASAN_WRITE_RANGE(ctx, to + to_length, from_length + 1); 39868d75effSDimitry Andric if (from_length > 0) { 39968d75effSDimitry Andric CHECK_RANGES_OVERLAP("strncat", to, to_length + copy_length + 1, 40068d75effSDimitry Andric from, copy_length); 40168d75effSDimitry Andric } 40268d75effSDimitry Andric } 40368d75effSDimitry Andric return REAL(strncat)(to, from, size); 40468d75effSDimitry Andric } 40568d75effSDimitry Andric 40668d75effSDimitry Andric INTERCEPTOR(char *, strcpy, char *to, const char *from) { 40768d75effSDimitry Andric void *ctx; 40868d75effSDimitry Andric ASAN_INTERCEPTOR_ENTER(ctx, strcpy); 40968d75effSDimitry Andric #if SANITIZER_MAC 41068d75effSDimitry Andric if (UNLIKELY(!asan_inited)) 41168d75effSDimitry Andric return REAL(strcpy)(to, from); 41268d75effSDimitry Andric #endif 41368d75effSDimitry Andric // strcpy is called from malloc_default_purgeable_zone() 41468d75effSDimitry Andric // in __asan::ReplaceSystemAlloc() on Mac. 41568d75effSDimitry Andric if (asan_init_is_running) { 41668d75effSDimitry Andric return REAL(strcpy)(to, from); 41768d75effSDimitry Andric } 41868d75effSDimitry Andric ENSURE_ASAN_INITED(); 41968d75effSDimitry Andric if (flags()->replace_str) { 42068d75effSDimitry Andric uptr from_size = REAL(strlen)(from) + 1; 42168d75effSDimitry Andric CHECK_RANGES_OVERLAP("strcpy", to, from_size, from, from_size); 42268d75effSDimitry Andric ASAN_READ_RANGE(ctx, from, from_size); 42368d75effSDimitry Andric ASAN_WRITE_RANGE(ctx, to, from_size); 42468d75effSDimitry Andric } 42568d75effSDimitry Andric return REAL(strcpy)(to, from); 42668d75effSDimitry Andric } 42768d75effSDimitry Andric 42868d75effSDimitry Andric INTERCEPTOR(char*, strdup, const char *s) { 42968d75effSDimitry Andric void *ctx; 43068d75effSDimitry Andric ASAN_INTERCEPTOR_ENTER(ctx, strdup); 43168d75effSDimitry Andric if (UNLIKELY(!asan_inited)) return internal_strdup(s); 43268d75effSDimitry Andric ENSURE_ASAN_INITED(); 43368d75effSDimitry Andric uptr length = REAL(strlen)(s); 43468d75effSDimitry Andric if (flags()->replace_str) { 43568d75effSDimitry Andric ASAN_READ_RANGE(ctx, s, length + 1); 43668d75effSDimitry Andric } 43768d75effSDimitry Andric GET_STACK_TRACE_MALLOC; 43868d75effSDimitry Andric void *new_mem = asan_malloc(length + 1, &stack); 43968d75effSDimitry Andric REAL(memcpy)(new_mem, s, length + 1); 44068d75effSDimitry Andric return reinterpret_cast<char*>(new_mem); 44168d75effSDimitry Andric } 44268d75effSDimitry Andric 44368d75effSDimitry Andric #if ASAN_INTERCEPT___STRDUP 44468d75effSDimitry Andric INTERCEPTOR(char*, __strdup, const char *s) { 44568d75effSDimitry Andric void *ctx; 44668d75effSDimitry Andric ASAN_INTERCEPTOR_ENTER(ctx, strdup); 44768d75effSDimitry Andric if (UNLIKELY(!asan_inited)) return internal_strdup(s); 44868d75effSDimitry Andric ENSURE_ASAN_INITED(); 44968d75effSDimitry Andric uptr length = REAL(strlen)(s); 45068d75effSDimitry Andric if (flags()->replace_str) { 45168d75effSDimitry Andric ASAN_READ_RANGE(ctx, s, length + 1); 45268d75effSDimitry Andric } 45368d75effSDimitry Andric GET_STACK_TRACE_MALLOC; 45468d75effSDimitry Andric void *new_mem = asan_malloc(length + 1, &stack); 45568d75effSDimitry Andric REAL(memcpy)(new_mem, s, length + 1); 45668d75effSDimitry Andric return reinterpret_cast<char*>(new_mem); 45768d75effSDimitry Andric } 45868d75effSDimitry Andric #endif // ASAN_INTERCEPT___STRDUP 45968d75effSDimitry Andric 46068d75effSDimitry Andric INTERCEPTOR(char*, strncpy, char *to, const char *from, uptr size) { 46168d75effSDimitry Andric void *ctx; 46268d75effSDimitry Andric ASAN_INTERCEPTOR_ENTER(ctx, strncpy); 46368d75effSDimitry Andric ENSURE_ASAN_INITED(); 46468d75effSDimitry Andric if (flags()->replace_str) { 46568d75effSDimitry Andric uptr from_size = Min(size, MaybeRealStrnlen(from, size) + 1); 46668d75effSDimitry Andric CHECK_RANGES_OVERLAP("strncpy", to, from_size, from, from_size); 46768d75effSDimitry Andric ASAN_READ_RANGE(ctx, from, from_size); 46868d75effSDimitry Andric ASAN_WRITE_RANGE(ctx, to, size); 46968d75effSDimitry Andric } 47068d75effSDimitry Andric return REAL(strncpy)(to, from, size); 47168d75effSDimitry Andric } 47268d75effSDimitry Andric 47368d75effSDimitry Andric INTERCEPTOR(long, strtol, const char *nptr, char **endptr, int base) { 47468d75effSDimitry Andric void *ctx; 47568d75effSDimitry Andric ASAN_INTERCEPTOR_ENTER(ctx, strtol); 47668d75effSDimitry Andric ENSURE_ASAN_INITED(); 47768d75effSDimitry Andric if (!flags()->replace_str) { 47868d75effSDimitry Andric return REAL(strtol)(nptr, endptr, base); 47968d75effSDimitry Andric } 48068d75effSDimitry Andric char *real_endptr; 48168d75effSDimitry Andric long result = REAL(strtol)(nptr, &real_endptr, base); 48268d75effSDimitry Andric StrtolFixAndCheck(ctx, nptr, endptr, real_endptr, base); 48368d75effSDimitry Andric return result; 48468d75effSDimitry Andric } 48568d75effSDimitry Andric 48668d75effSDimitry Andric INTERCEPTOR(int, atoi, const char *nptr) { 48768d75effSDimitry Andric void *ctx; 48868d75effSDimitry Andric ASAN_INTERCEPTOR_ENTER(ctx, atoi); 48968d75effSDimitry Andric #if SANITIZER_MAC 49068d75effSDimitry Andric if (UNLIKELY(!asan_inited)) return REAL(atoi)(nptr); 49168d75effSDimitry Andric #endif 49268d75effSDimitry Andric ENSURE_ASAN_INITED(); 49368d75effSDimitry Andric if (!flags()->replace_str) { 49468d75effSDimitry Andric return REAL(atoi)(nptr); 49568d75effSDimitry Andric } 49668d75effSDimitry Andric char *real_endptr; 49768d75effSDimitry Andric // "man atoi" tells that behavior of atoi(nptr) is the same as 49868d75effSDimitry Andric // strtol(nptr, 0, 10), i.e. it sets errno to ERANGE if the 49968d75effSDimitry Andric // parsed integer can't be stored in *long* type (even if it's 50068d75effSDimitry Andric // different from int). So, we just imitate this behavior. 50168d75effSDimitry Andric int result = REAL(strtol)(nptr, &real_endptr, 10); 50268d75effSDimitry Andric FixRealStrtolEndptr(nptr, &real_endptr); 50368d75effSDimitry Andric ASAN_READ_STRING(ctx, nptr, (real_endptr - nptr) + 1); 50468d75effSDimitry Andric return result; 50568d75effSDimitry Andric } 50668d75effSDimitry Andric 50768d75effSDimitry Andric INTERCEPTOR(long, atol, const char *nptr) { 50868d75effSDimitry Andric void *ctx; 50968d75effSDimitry Andric ASAN_INTERCEPTOR_ENTER(ctx, atol); 51068d75effSDimitry Andric #if SANITIZER_MAC 51168d75effSDimitry Andric if (UNLIKELY(!asan_inited)) return REAL(atol)(nptr); 51268d75effSDimitry Andric #endif 51368d75effSDimitry Andric ENSURE_ASAN_INITED(); 51468d75effSDimitry Andric if (!flags()->replace_str) { 51568d75effSDimitry Andric return REAL(atol)(nptr); 51668d75effSDimitry Andric } 51768d75effSDimitry Andric char *real_endptr; 51868d75effSDimitry Andric long result = REAL(strtol)(nptr, &real_endptr, 10); 51968d75effSDimitry Andric FixRealStrtolEndptr(nptr, &real_endptr); 52068d75effSDimitry Andric ASAN_READ_STRING(ctx, nptr, (real_endptr - nptr) + 1); 52168d75effSDimitry Andric return result; 52268d75effSDimitry Andric } 52368d75effSDimitry Andric 52468d75effSDimitry Andric #if ASAN_INTERCEPT_ATOLL_AND_STRTOLL 52568d75effSDimitry Andric INTERCEPTOR(long long, strtoll, const char *nptr, char **endptr, int base) { 52668d75effSDimitry Andric void *ctx; 52768d75effSDimitry Andric ASAN_INTERCEPTOR_ENTER(ctx, strtoll); 52868d75effSDimitry Andric ENSURE_ASAN_INITED(); 52968d75effSDimitry Andric if (!flags()->replace_str) { 53068d75effSDimitry Andric return REAL(strtoll)(nptr, endptr, base); 53168d75effSDimitry Andric } 53268d75effSDimitry Andric char *real_endptr; 53368d75effSDimitry Andric long long result = REAL(strtoll)(nptr, &real_endptr, base); 53468d75effSDimitry Andric StrtolFixAndCheck(ctx, nptr, endptr, real_endptr, base); 53568d75effSDimitry Andric return result; 53668d75effSDimitry Andric } 53768d75effSDimitry Andric 53868d75effSDimitry Andric INTERCEPTOR(long long, atoll, const char *nptr) { 53968d75effSDimitry Andric void *ctx; 54068d75effSDimitry Andric ASAN_INTERCEPTOR_ENTER(ctx, atoll); 54168d75effSDimitry Andric ENSURE_ASAN_INITED(); 54268d75effSDimitry Andric if (!flags()->replace_str) { 54368d75effSDimitry Andric return REAL(atoll)(nptr); 54468d75effSDimitry Andric } 54568d75effSDimitry Andric char *real_endptr; 54668d75effSDimitry Andric long long result = REAL(strtoll)(nptr, &real_endptr, 10); 54768d75effSDimitry Andric FixRealStrtolEndptr(nptr, &real_endptr); 54868d75effSDimitry Andric ASAN_READ_STRING(ctx, nptr, (real_endptr - nptr) + 1); 54968d75effSDimitry Andric return result; 55068d75effSDimitry Andric } 55168d75effSDimitry Andric #endif // ASAN_INTERCEPT_ATOLL_AND_STRTOLL 55268d75effSDimitry Andric 55368d75effSDimitry Andric #if ASAN_INTERCEPT___CXA_ATEXIT || ASAN_INTERCEPT_ATEXIT 55468d75effSDimitry Andric static void AtCxaAtexit(void *unused) { 55568d75effSDimitry Andric (void)unused; 55668d75effSDimitry Andric StopInitOrderChecking(); 55768d75effSDimitry Andric } 55868d75effSDimitry Andric #endif 55968d75effSDimitry Andric 56068d75effSDimitry Andric #if ASAN_INTERCEPT___CXA_ATEXIT 56168d75effSDimitry Andric INTERCEPTOR(int, __cxa_atexit, void (*func)(void *), void *arg, 56268d75effSDimitry Andric void *dso_handle) { 56368d75effSDimitry Andric #if SANITIZER_MAC 56468d75effSDimitry Andric if (UNLIKELY(!asan_inited)) return REAL(__cxa_atexit)(func, arg, dso_handle); 56568d75effSDimitry Andric #endif 56668d75effSDimitry Andric ENSURE_ASAN_INITED(); 56768d75effSDimitry Andric #if CAN_SANITIZE_LEAKS 56868d75effSDimitry Andric __lsan::ScopedInterceptorDisabler disabler; 56968d75effSDimitry Andric #endif 57068d75effSDimitry Andric int res = REAL(__cxa_atexit)(func, arg, dso_handle); 57168d75effSDimitry Andric REAL(__cxa_atexit)(AtCxaAtexit, nullptr, nullptr); 57268d75effSDimitry Andric return res; 57368d75effSDimitry Andric } 57468d75effSDimitry Andric #endif // ASAN_INTERCEPT___CXA_ATEXIT 57568d75effSDimitry Andric 57668d75effSDimitry Andric #if ASAN_INTERCEPT_ATEXIT 57768d75effSDimitry Andric INTERCEPTOR(int, atexit, void (*func)()) { 57868d75effSDimitry Andric ENSURE_ASAN_INITED(); 57968d75effSDimitry Andric #if CAN_SANITIZE_LEAKS 58068d75effSDimitry Andric __lsan::ScopedInterceptorDisabler disabler; 58168d75effSDimitry Andric #endif 58268d75effSDimitry Andric // Avoid calling real atexit as it is unrechable on at least on Linux. 58368d75effSDimitry Andric int res = REAL(__cxa_atexit)((void (*)(void *a))func, nullptr, nullptr); 58468d75effSDimitry Andric REAL(__cxa_atexit)(AtCxaAtexit, nullptr, nullptr); 58568d75effSDimitry Andric return res; 58668d75effSDimitry Andric } 58768d75effSDimitry Andric #endif 58868d75effSDimitry Andric 58968d75effSDimitry Andric #if ASAN_INTERCEPT_PTHREAD_ATFORK 59068d75effSDimitry Andric extern "C" { 59168d75effSDimitry Andric extern int _pthread_atfork(void (*prepare)(), void (*parent)(), 59268d75effSDimitry Andric void (*child)()); 59368d75effSDimitry Andric }; 59468d75effSDimitry Andric 59568d75effSDimitry Andric INTERCEPTOR(int, pthread_atfork, void (*prepare)(), void (*parent)(), 59668d75effSDimitry Andric void (*child)()) { 59768d75effSDimitry Andric #if CAN_SANITIZE_LEAKS 59868d75effSDimitry Andric __lsan::ScopedInterceptorDisabler disabler; 59968d75effSDimitry Andric #endif 60068d75effSDimitry Andric // REAL(pthread_atfork) cannot be called due to symbol indirections at least 60168d75effSDimitry Andric // on NetBSD 60268d75effSDimitry Andric return _pthread_atfork(prepare, parent, child); 60368d75effSDimitry Andric } 60468d75effSDimitry Andric #endif 60568d75effSDimitry Andric 60668d75effSDimitry Andric #if ASAN_INTERCEPT_VFORK 60768d75effSDimitry Andric DEFINE_REAL(int, vfork) 60868d75effSDimitry Andric DECLARE_EXTERN_INTERCEPTOR_AND_WRAPPER(int, vfork) 60968d75effSDimitry Andric #endif 61068d75effSDimitry Andric 61168d75effSDimitry Andric // ---------------------- InitializeAsanInterceptors ---------------- {{{1 61268d75effSDimitry Andric namespace __asan { 61368d75effSDimitry Andric void InitializeAsanInterceptors() { 61468d75effSDimitry Andric static bool was_called_once; 61568d75effSDimitry Andric CHECK(!was_called_once); 61668d75effSDimitry Andric was_called_once = true; 61768d75effSDimitry Andric InitializeCommonInterceptors(); 61868d75effSDimitry Andric InitializeSignalInterceptors(); 61968d75effSDimitry Andric 62068d75effSDimitry Andric // Intercept str* functions. 62168d75effSDimitry Andric ASAN_INTERCEPT_FUNC(strcat); 62268d75effSDimitry Andric ASAN_INTERCEPT_FUNC(strcpy); 62368d75effSDimitry Andric ASAN_INTERCEPT_FUNC(strncat); 62468d75effSDimitry Andric ASAN_INTERCEPT_FUNC(strncpy); 62568d75effSDimitry Andric ASAN_INTERCEPT_FUNC(strdup); 62668d75effSDimitry Andric #if ASAN_INTERCEPT___STRDUP 62768d75effSDimitry Andric ASAN_INTERCEPT_FUNC(__strdup); 62868d75effSDimitry Andric #endif 62968d75effSDimitry Andric #if ASAN_INTERCEPT_INDEX && ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX 63068d75effSDimitry Andric ASAN_INTERCEPT_FUNC(index); 63168d75effSDimitry Andric #endif 63268d75effSDimitry Andric 63368d75effSDimitry Andric ASAN_INTERCEPT_FUNC(atoi); 63468d75effSDimitry Andric ASAN_INTERCEPT_FUNC(atol); 63568d75effSDimitry Andric ASAN_INTERCEPT_FUNC(strtol); 63668d75effSDimitry Andric #if ASAN_INTERCEPT_ATOLL_AND_STRTOLL 63768d75effSDimitry Andric ASAN_INTERCEPT_FUNC(atoll); 63868d75effSDimitry Andric ASAN_INTERCEPT_FUNC(strtoll); 63968d75effSDimitry Andric #endif 64068d75effSDimitry Andric 64168d75effSDimitry Andric // Intecept jump-related functions. 64268d75effSDimitry Andric ASAN_INTERCEPT_FUNC(longjmp); 64368d75effSDimitry Andric 64468d75effSDimitry Andric #if ASAN_INTERCEPT_SWAPCONTEXT 64568d75effSDimitry Andric ASAN_INTERCEPT_FUNC(swapcontext); 64668d75effSDimitry Andric #endif 64768d75effSDimitry Andric #if ASAN_INTERCEPT__LONGJMP 64868d75effSDimitry Andric ASAN_INTERCEPT_FUNC(_longjmp); 64968d75effSDimitry Andric #endif 65068d75effSDimitry Andric #if ASAN_INTERCEPT___LONGJMP_CHK 65168d75effSDimitry Andric ASAN_INTERCEPT_FUNC(__longjmp_chk); 65268d75effSDimitry Andric #endif 65368d75effSDimitry Andric #if ASAN_INTERCEPT_SIGLONGJMP 65468d75effSDimitry Andric ASAN_INTERCEPT_FUNC(siglongjmp); 65568d75effSDimitry Andric #endif 65668d75effSDimitry Andric 65768d75effSDimitry Andric // Intercept exception handling functions. 65868d75effSDimitry Andric #if ASAN_INTERCEPT___CXA_THROW 65968d75effSDimitry Andric ASAN_INTERCEPT_FUNC(__cxa_throw); 66068d75effSDimitry Andric #endif 66168d75effSDimitry Andric #if ASAN_INTERCEPT___CXA_RETHROW_PRIMARY_EXCEPTION 66268d75effSDimitry Andric ASAN_INTERCEPT_FUNC(__cxa_rethrow_primary_exception); 66368d75effSDimitry Andric #endif 66468d75effSDimitry Andric // Indirectly intercept std::rethrow_exception. 66568d75effSDimitry Andric #if ASAN_INTERCEPT__UNWIND_RAISEEXCEPTION 66668d75effSDimitry Andric INTERCEPT_FUNCTION(_Unwind_RaiseException); 66768d75effSDimitry Andric #endif 66868d75effSDimitry Andric // Indirectly intercept std::rethrow_exception. 66968d75effSDimitry Andric #if ASAN_INTERCEPT__UNWIND_SJLJ_RAISEEXCEPTION 67068d75effSDimitry Andric INTERCEPT_FUNCTION(_Unwind_SjLj_RaiseException); 67168d75effSDimitry Andric #endif 67268d75effSDimitry Andric 67368d75effSDimitry Andric // Intercept threading-related functions 67468d75effSDimitry Andric #if ASAN_INTERCEPT_PTHREAD_CREATE 67568d75effSDimitry Andric #if defined(ASAN_PTHREAD_CREATE_VERSION) 67668d75effSDimitry Andric ASAN_INTERCEPT_FUNC_VER(pthread_create, ASAN_PTHREAD_CREATE_VERSION); 67768d75effSDimitry Andric #else 67868d75effSDimitry Andric ASAN_INTERCEPT_FUNC(pthread_create); 67968d75effSDimitry Andric #endif 68068d75effSDimitry Andric ASAN_INTERCEPT_FUNC(pthread_join); 68168d75effSDimitry Andric #endif 68268d75effSDimitry Andric 68368d75effSDimitry Andric // Intercept atexit function. 68468d75effSDimitry Andric #if ASAN_INTERCEPT___CXA_ATEXIT 68568d75effSDimitry Andric ASAN_INTERCEPT_FUNC(__cxa_atexit); 68668d75effSDimitry Andric #endif 68768d75effSDimitry Andric 68868d75effSDimitry Andric #if ASAN_INTERCEPT_ATEXIT 68968d75effSDimitry Andric ASAN_INTERCEPT_FUNC(atexit); 69068d75effSDimitry Andric #endif 69168d75effSDimitry Andric 69268d75effSDimitry Andric #if ASAN_INTERCEPT_PTHREAD_ATFORK 69368d75effSDimitry Andric ASAN_INTERCEPT_FUNC(pthread_atfork); 69468d75effSDimitry Andric #endif 69568d75effSDimitry Andric 69668d75effSDimitry Andric #if ASAN_INTERCEPT_VFORK 69768d75effSDimitry Andric ASAN_INTERCEPT_FUNC(vfork); 69868d75effSDimitry Andric #endif 69968d75effSDimitry Andric 70068d75effSDimitry Andric InitializePlatformInterceptors(); 70168d75effSDimitry Andric 70268d75effSDimitry Andric VReport(1, "AddressSanitizer: libc interceptors initialized\n"); 70368d75effSDimitry Andric } 70468d75effSDimitry Andric 70568d75effSDimitry Andric } // namespace __asan 70668d75effSDimitry Andric 70768d75effSDimitry Andric #endif // !SANITIZER_FUCHSIA 708