diff options
Diffstat (limited to 'contrib/llvm-project/compiler-rt/lib/asan/asan_interceptors.cpp')
-rw-r--r-- | contrib/llvm-project/compiler-rt/lib/asan/asan_interceptors.cpp | 163 |
1 files changed, 126 insertions, 37 deletions
diff --git a/contrib/llvm-project/compiler-rt/lib/asan/asan_interceptors.cpp b/contrib/llvm-project/compiler-rt/lib/asan/asan_interceptors.cpp index 776f512d08a0..b9b82564b330 100644 --- a/contrib/llvm-project/compiler-rt/lib/asan/asan_interceptors.cpp +++ b/contrib/llvm-project/compiler-rt/lib/asan/asan_interceptors.cpp @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// #include "asan_interceptors.h" + #include "asan_allocator.h" #include "asan_internal.h" #include "asan_mapping.h" @@ -20,7 +21,10 @@ #include "asan_stack.h" #include "asan_stats.h" #include "asan_suppressions.h" +#include "asan_thread.h" #include "lsan/lsan_common.h" +#include "sanitizer_common/sanitizer_errno.h" +#include "sanitizer_common/sanitizer_internal_defs.h" #include "sanitizer_common/sanitizer_libc.h" // There is no general interception at all on Fuchsia. @@ -84,12 +88,6 @@ using namespace __asan; DECLARE_REAL_AND_INTERCEPTOR(void *, malloc, uptr) DECLARE_REAL_AND_INTERCEPTOR(void, free, void *) -#define ASAN_INTERCEPTOR_ENTER(ctx, func) \ - AsanInterceptorContext _ctx = {#func}; \ - ctx = (void *)&_ctx; \ - (void) ctx; \ - -#define COMMON_INTERCEPT_FUNCTION(name) ASAN_INTERCEPT_FUNC(name) #define COMMON_INTERCEPT_FUNCTION_VER(name, ver) \ ASAN_INTERCEPT_FUNC_VER(name, ver) #define COMMON_INTERCEPT_FUNCTION_VER_UNVERSIONED_FALLBACK(name, ver) \ @@ -149,22 +147,46 @@ DECLARE_REAL_AND_INTERCEPTOR(void, free, void *) *begin = *end = 0; \ } -#define COMMON_INTERCEPTOR_MEMMOVE_IMPL(ctx, to, from, size) \ - do { \ - ASAN_INTERCEPTOR_ENTER(ctx, memmove); \ - ASAN_MEMMOVE_IMPL(ctx, to, from, size); \ - } while (false) +template <class Mmap> +static void* mmap_interceptor(Mmap real_mmap, void *addr, SIZE_T length, + int prot, int flags, int fd, OFF64_T offset) { + void *res = real_mmap(addr, length, prot, flags, fd, offset); + if (length && res != (void *)-1) { + const uptr beg = reinterpret_cast<uptr>(res); + DCHECK(IsAligned(beg, GetPageSize())); + SIZE_T rounded_length = RoundUpTo(length, GetPageSize()); + // Only unpoison shadow if it's an ASAN managed address. + if (AddrIsInMem(beg) && AddrIsInMem(beg + rounded_length - 1)) + PoisonShadow(beg, RoundUpTo(length, GetPageSize()), 0); + } + return res; +} -#define COMMON_INTERCEPTOR_MEMCPY_IMPL(ctx, to, from, size) \ - do { \ - ASAN_INTERCEPTOR_ENTER(ctx, memcpy); \ - ASAN_MEMCPY_IMPL(ctx, to, from, size); \ +template <class Munmap> +static int munmap_interceptor(Munmap real_munmap, void *addr, SIZE_T length) { + // We should not tag if munmap fail, but it's to late to tag after + // real_munmap, as the pages could be mmaped by another thread. + const uptr beg = reinterpret_cast<uptr>(addr); + if (length && IsAligned(beg, GetPageSize())) { + SIZE_T rounded_length = RoundUpTo(length, GetPageSize()); + // Protect from unmapping the shadow. + if (AddrIsInMem(beg) && AddrIsInMem(beg + rounded_length - 1)) + PoisonShadow(beg, rounded_length, 0); + } + return real_munmap(addr, length); +} + +# define COMMON_INTERCEPTOR_MMAP_IMPL(ctx, mmap, addr, length, prot, flags, \ + fd, offset) \ + do { \ + (void)(ctx); \ + return mmap_interceptor(REAL(mmap), addr, sz, prot, flags, fd, off); \ } while (false) -#define COMMON_INTERCEPTOR_MEMSET_IMPL(ctx, block, c, size) \ - do { \ - ASAN_INTERCEPTOR_ENTER(ctx, memset); \ - ASAN_MEMSET_IMPL(ctx, block, c, size); \ +# define COMMON_INTERCEPTOR_MUNMAP_IMPL(ctx, addr, length) \ + do { \ + (void)(ctx); \ + return munmap_interceptor(REAL(munmap), addr, sz); \ } while (false) #if CAN_SANITIZE_LEAKS @@ -172,6 +194,8 @@ DECLARE_REAL_AND_INTERCEPTOR(void, free, void *) __lsan::ScopedInterceptorDisabler disabler #endif +#define SIGNAL_INTERCEPTOR_ENTER() ENSURE_ASAN_INITED() + #include "sanitizer_common/sanitizer_common_interceptors.inc" #include "sanitizer_common/sanitizer_signal_interceptors.inc" @@ -196,19 +220,26 @@ DECLARE_REAL_AND_INTERCEPTOR(void, free, void *) static thread_return_t THREAD_CALLING_CONV asan_thread_start(void *arg) { AsanThread *t = (AsanThread *)arg; SetCurrentThread(t); - return t->ThreadStart(GetTid()); + auto self = GetThreadSelf(); + auto args = asanThreadArgRetval().GetArgs(self); + thread_return_t retval = t->ThreadStart(GetTid()); + asanThreadArgRetval().Finish(self, retval); + CHECK_EQ(args.arg_retval, t->get_arg()); + return retval; } -INTERCEPTOR(int, pthread_create, void *thread, - void *attr, void *(*start_routine)(void*), void *arg) { +INTERCEPTOR(int, pthread_create, void *thread, void *attr, + void *(*start_routine)(void *), void *arg) { EnsureMainThreadIDIsCorrect(); // Strict init-order checking is thread-hostile. if (flags()->strict_init_order) StopInitOrderChecking(); GET_STACK_TRACE_THREAD; - int detached = 0; - if (attr) - REAL(pthread_attr_getdetachstate)(attr, &detached); + bool detached = [attr]() { + int d = 0; + return attr && !REAL(pthread_attr_getdetachstate)(attr, &d) && + IsStateDetached(d); + }(); u32 current_tid = GetCurrentTidOrInvalid(); AsanThread *t = @@ -220,10 +251,13 @@ INTERCEPTOR(int, pthread_create, void *thread, // stored by pthread for future reuse even after thread destruction, and // the linked list it's stored in doesn't even hold valid pointers to the // objects, the latter are calculated by obscure pointer arithmetic. -#if CAN_SANITIZE_LEAKS +# if CAN_SANITIZE_LEAKS __lsan::ScopedInterceptorDisabler disabler; -#endif - result = REAL(pthread_create)(thread, attr, asan_thread_start, t); +# endif + asanThreadArgRetval().Create(detached, {start_routine, arg}, [&]() -> uptr { + result = REAL(pthread_create)(thread, attr, asan_thread_start, t); + return result ? 0 : *(uptr *)(thread); + }); } if (result != 0) { // If the thread didn't start delete the AsanThread to avoid leaking it. @@ -234,9 +268,51 @@ INTERCEPTOR(int, pthread_create, void *thread, return result; } -INTERCEPTOR(int, pthread_join, void *t, void **arg) { - return real_pthread_join(t, arg); +INTERCEPTOR(int, pthread_join, void *thread, void **retval) { + int result; + asanThreadArgRetval().Join((uptr)thread, [&]() { + result = REAL(pthread_join)(thread, retval); + return !result; + }); + return result; +} + +INTERCEPTOR(int, pthread_detach, void *thread) { + int result; + asanThreadArgRetval().Detach((uptr)thread, [&]() { + result = REAL(pthread_detach)(thread); + return !result; + }); + return result; +} + +INTERCEPTOR(int, pthread_exit, void *retval) { + asanThreadArgRetval().Finish(GetThreadSelf(), retval); + return REAL(pthread_exit)(retval); +} + +# if ASAN_INTERCEPT_TRYJOIN +INTERCEPTOR(int, pthread_tryjoin_np, void *thread, void **ret) { + int result; + asanThreadArgRetval().Join((uptr)thread, [&]() { + result = REAL(pthread_tryjoin_np)(thread, ret); + return !result; + }); + return result; +} +# endif + +# if ASAN_INTERCEPT_TIMEDJOIN +INTERCEPTOR(int, pthread_timedjoin_np, void *thread, void **ret, + const struct timespec *abstime) { + int result; + asanThreadArgRetval().Join((uptr)thread, [&]() { + result = REAL(pthread_timedjoin_np)(thread, ret, abstime); + return !result; + }); + return result; } +# endif DEFINE_REAL_PTHREAD_FUNCTIONS #endif // ASAN_INTERCEPT_PTHREAD_CREATE @@ -388,7 +464,7 @@ INTERCEPTOR(_Unwind_Reason_Code, _Unwind_SjLj_RaiseException, #if ASAN_INTERCEPT_INDEX # if ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX INTERCEPTOR(char*, index, const char *string, int c) - ALIAS(WRAPPER_NAME(strchr)); + ALIAS(WRAP(strchr)); # else # if SANITIZER_APPLE DECLARE_REAL(char*, index, const char *string, int c) @@ -474,7 +550,9 @@ INTERCEPTOR(char*, strdup, const char *s) { } GET_STACK_TRACE_MALLOC; void *new_mem = asan_malloc(length + 1, &stack); - REAL(memcpy)(new_mem, s, length + 1); + if (new_mem) { + REAL(memcpy)(new_mem, s, length + 1); + } return reinterpret_cast<char*>(new_mem); } @@ -490,7 +568,9 @@ INTERCEPTOR(char*, __strdup, const char *s) { } GET_STACK_TRACE_MALLOC; void *new_mem = asan_malloc(length + 1, &stack); - REAL(memcpy)(new_mem, s, length + 1); + if (new_mem) { + REAL(memcpy)(new_mem, s, length + 1); + } return reinterpret_cast<char*>(new_mem); } #endif // ASAN_INTERCEPT___STRDUP @@ -652,6 +732,7 @@ void InitializeAsanInterceptors() { static bool was_called_once; CHECK(!was_called_once); was_called_once = true; + InitializePlatformInterceptors(); InitializeCommonInterceptors(); InitializeSignalInterceptors(); @@ -702,11 +783,11 @@ void InitializeAsanInterceptors() { #endif // Indirectly intercept std::rethrow_exception. #if ASAN_INTERCEPT__UNWIND_RAISEEXCEPTION - INTERCEPT_FUNCTION(_Unwind_RaiseException); + ASAN_INTERCEPT_FUNC(_Unwind_RaiseException); #endif // Indirectly intercept std::rethrow_exception. #if ASAN_INTERCEPT__UNWIND_SJLJ_RAISEEXCEPTION - INTERCEPT_FUNCTION(_Unwind_SjLj_RaiseException); + ASAN_INTERCEPT_FUNC(_Unwind_SjLj_RaiseException); #endif // Intercept threading-related functions @@ -718,6 +799,16 @@ void InitializeAsanInterceptors() { ASAN_INTERCEPT_FUNC(pthread_create); #endif ASAN_INTERCEPT_FUNC(pthread_join); + ASAN_INTERCEPT_FUNC(pthread_detach); + ASAN_INTERCEPT_FUNC(pthread_exit); +# endif + +# if ASAN_INTERCEPT_TIMEDJOIN + ASAN_INTERCEPT_FUNC(pthread_timedjoin_np); +#endif + +#if ASAN_INTERCEPT_TRYJOIN + ASAN_INTERCEPT_FUNC(pthread_tryjoin_np); #endif // Intercept atexit function. @@ -737,8 +828,6 @@ void InitializeAsanInterceptors() { ASAN_INTERCEPT_FUNC(vfork); #endif - InitializePlatformInterceptors(); - VReport(1, "AddressSanitizer: libc interceptors initialized\n"); } |