diff options
Diffstat (limited to 'contrib/compiler-rt/lib/msan/msan_interceptors.cc')
-rw-r--r-- | contrib/compiler-rt/lib/msan/msan_interceptors.cc | 76 |
1 files changed, 70 insertions, 6 deletions
diff --git a/contrib/compiler-rt/lib/msan/msan_interceptors.cc b/contrib/compiler-rt/lib/msan/msan_interceptors.cc index b3429bcf06b5..497f943a8a0e 100644 --- a/contrib/compiler-rt/lib/msan/msan_interceptors.cc +++ b/contrib/compiler-rt/lib/msan/msan_interceptors.cc @@ -34,11 +34,13 @@ #include "sanitizer_common/sanitizer_libc.h" #include "sanitizer_common/sanitizer_linux.h" #include "sanitizer_common/sanitizer_tls_get_addr.h" +#include "sanitizer_common/sanitizer_vector.h" #if SANITIZER_NETBSD #define fstat __fstat50 #define gettimeofday __gettimeofday50 #define getrusage __getrusage50 +#define tzset __tzset50 #endif #include <stdarg.h> @@ -249,11 +251,11 @@ INTERCEPTOR(uptr, malloc_usable_size, void *ptr) { // temporary! The following is equivalent on all supported platforms but // aarch64 (which uses a different register for sret value). We have a test // to confirm that. -INTERCEPTOR(void, mallinfo, __sanitizer_mallinfo *sret) { +INTERCEPTOR(void, mallinfo, __sanitizer_struct_mallinfo *sret) { #ifdef __aarch64__ uptr r8; asm volatile("mov %0,x8" : "=r" (r8)); - sret = reinterpret_cast<__sanitizer_mallinfo*>(r8); + sret = reinterpret_cast<__sanitizer_struct_mallinfo*>(r8); #endif REAL(memset)(sret, 0, sizeof(*sret)); __msan_unpoison(sret, sizeof(*sret)); @@ -265,7 +267,7 @@ INTERCEPTOR(void, mallinfo, __sanitizer_mallinfo *sret) { #if !SANITIZER_FREEBSD && !SANITIZER_NETBSD INTERCEPTOR(int, mallopt, int cmd, int value) { - return -1; + return 0; } #define MSAN_MAYBE_INTERCEPT_MALLOPT INTERCEPT_FUNCTION(mallopt) #else @@ -1071,6 +1073,7 @@ extern char *tzname[2]; INTERCEPTOR(void, tzset, int fake) { ENSURE_MSAN_INITED(); + InterceptorScope interceptor_scope; REAL(tzset)(fake); if (tzname[0]) __msan_unpoison(tzname[0], REAL(strlen)(tzname[0]) + 1); @@ -1084,23 +1087,80 @@ struct MSanAtExitRecord { void *arg; }; -void MSanAtExitWrapper(void *arg) { +struct InterceptorContext { + BlockingMutex atexit_mu; + Vector<struct MSanAtExitRecord *> AtExitStack; + + InterceptorContext() + : AtExitStack() { + } +}; + +static ALIGNED(64) char interceptor_placeholder[sizeof(InterceptorContext)]; +InterceptorContext *interceptor_ctx() { + return reinterpret_cast<InterceptorContext*>(&interceptor_placeholder[0]); +} + +void MSanAtExitWrapper() { + MSanAtExitRecord *r; + { + BlockingMutexLock l(&interceptor_ctx()->atexit_mu); + + uptr element = interceptor_ctx()->AtExitStack.Size() - 1; + r = interceptor_ctx()->AtExitStack[element]; + interceptor_ctx()->AtExitStack.PopBack(); + } + + UnpoisonParam(1); + ((void(*)())r->func)(); + InternalFree(r); +} + +void MSanCxaAtExitWrapper(void *arg) { UnpoisonParam(1); MSanAtExitRecord *r = (MSanAtExitRecord *)arg; r->func(r->arg); InternalFree(r); } +static int setup_at_exit_wrapper(void(*f)(), void *arg, void *dso); + // Unpoison argument shadow for C++ module destructors. INTERCEPTOR(int, __cxa_atexit, void (*func)(void *), void *arg, void *dso_handle) { if (msan_init_is_running) return REAL(__cxa_atexit)(func, arg, dso_handle); + return setup_at_exit_wrapper((void(*)())func, arg, dso_handle); +} + +// Unpoison argument shadow for C++ module destructors. +INTERCEPTOR(int, atexit, void (*func)()) { + // Avoid calling real atexit as it is unrechable on at least on Linux. + if (msan_init_is_running) + return REAL(__cxa_atexit)((void (*)(void *a))func, 0, 0); + return setup_at_exit_wrapper((void(*)())func, 0, 0); +} + +static int setup_at_exit_wrapper(void(*f)(), void *arg, void *dso) { ENSURE_MSAN_INITED(); MSanAtExitRecord *r = (MSanAtExitRecord *)InternalAlloc(sizeof(MSanAtExitRecord)); - r->func = func; + r->func = (void(*)(void *a))f; r->arg = arg; - return REAL(__cxa_atexit)(MSanAtExitWrapper, r, dso_handle); + int res; + if (!dso) { + // NetBSD does not preserve the 2nd argument if dso is equal to 0 + // Store ctx in a local stack-like structure + + BlockingMutexLock l(&interceptor_ctx()->atexit_mu); + + res = REAL(__cxa_atexit)((void (*)(void *a))MSanAtExitWrapper, 0, 0); + if (!res) { + interceptor_ctx()->AtExitStack.PushBack(r); + } + } else { + res = REAL(__cxa_atexit)(MSanCxaAtExitWrapper, r, dso); + } + return res; } static void BeforeFork() { @@ -1520,6 +1580,9 @@ namespace __msan { void InitializeInterceptors() { static int inited = 0; CHECK_EQ(inited, 0); + + new(interceptor_ctx()) InterceptorContext(); + InitializeCommonInterceptors(); InitializeSignalInterceptors(); @@ -1629,6 +1692,7 @@ void InitializeInterceptors() { INTERCEPT_FUNCTION(pthread_join); INTERCEPT_FUNCTION(tzset); + INTERCEPT_FUNCTION(atexit); INTERCEPT_FUNCTION(__cxa_atexit); INTERCEPT_FUNCTION(shmat); INTERCEPT_FUNCTION(fork); |