diff options
author | Kamil Rytarowski <n54@gmx.com> | 2019-09-21 07:30:42 +0000 |
---|---|---|
committer | Kamil Rytarowski <n54@gmx.com> | 2019-09-21 07:30:42 +0000 |
commit | 96b852a95bebc7c2d9da09975a4764c365167621 (patch) | |
tree | ef6cf465bc7fac9830d1ba6a74ab43472b7a0681 /lib | |
parent | dc2e8074dc573a070e71da4be3d97c5f6b765dba (diff) | |
download | compiler-rt-96b852a95bebc7c2d9da09975a4764c365167621.tar.gz |
Stop tracking atexit/__cxa_atexit/pthread_atfork allocations in LSan/NetBSD
Summary:
The atexit(3) and __cxa_atexit() calls allocate internally memory and free on exit,
after executing all callback. This causes false positives as DoLeakCheck() is called
from the atexit handler. In the LSan/ASan tests there are strict checks triggering
false positives here.
Intercept all atexit(3) and __cxa_atexit() calls and disable LSan when calling the
real functions.
Stop tracing allocations in pthread_atfork(3) funtions, as there are performed
internal allocations that are not freed for the time of running StopTheWorld()
code. This avoids false-positives.
The same changes have to be replicated in the ASan and LSan runtime.
Non-NetBSD OSs are not tested and this code is restricted to NetBSD only.
Reviewers: dvyukov, joerg, mgorny, vitalybuka, eugenis
Reviewed By: vitalybuka
Subscribers: jfb, llvm-commits, #sanitizers
Tags: #sanitizers, #llvm
Differential Revision: https://reviews.llvm.org/D67331
git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@372459 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r-- | lib/asan/asan_interceptors.cpp | 44 | ||||
-rw-r--r-- | lib/asan/asan_interceptors.h | 12 | ||||
-rw-r--r-- | lib/lsan/lsan_interceptors.cpp | 42 | ||||
-rw-r--r-- | lib/sanitizer_common/sanitizer_platform_interceptors.h | 4 |
4 files changed, 101 insertions, 1 deletions
diff --git a/lib/asan/asan_interceptors.cpp b/lib/asan/asan_interceptors.cpp index cea4d63e6..ec9589338 100644 --- a/lib/asan/asan_interceptors.cpp +++ b/lib/asan/asan_interceptors.cpp @@ -560,24 +560,58 @@ INTERCEPTOR(long long, atoll, const char *nptr) { } #endif // ASAN_INTERCEPT_ATOLL_AND_STRTOLL -#if ASAN_INTERCEPT___CXA_ATEXIT +#if ASAN_INTERCEPT___CXA_ATEXIT || ASAN_INTERCEPT_ATEXIT static void AtCxaAtexit(void *unused) { (void)unused; StopInitOrderChecking(); } +#endif +#if ASAN_INTERCEPT___CXA_ATEXIT INTERCEPTOR(int, __cxa_atexit, void (*func)(void *), void *arg, void *dso_handle) { #if SANITIZER_MAC if (UNLIKELY(!asan_inited)) return REAL(__cxa_atexit)(func, arg, dso_handle); #endif ENSURE_ASAN_INITED(); +#if CAN_SANITIZE_LEAKS + __lsan::ScopedInterceptorDisabler disabler; +#endif int res = REAL(__cxa_atexit)(func, arg, dso_handle); REAL(__cxa_atexit)(AtCxaAtexit, nullptr, nullptr); return res; } #endif // ASAN_INTERCEPT___CXA_ATEXIT +#if ASAN_INTERCEPT_ATEXIT +INTERCEPTOR(int, atexit, void (*func)()) { + ENSURE_ASAN_INITED(); +#if CAN_SANITIZE_LEAKS + __lsan::ScopedInterceptorDisabler disabler; +#endif + // Avoid calling real atexit as it is unrechable on at least on Linux. + int res = REAL(__cxa_atexit)((void (*)(void *a))func, nullptr, nullptr); + REAL(__cxa_atexit)(AtCxaAtexit, nullptr, nullptr); + return res; +} +#endif + +#if ASAN_INTERCEPT_PTHREAD_ATFORK +extern "C" { +extern int _pthread_atfork(void (*prepare)(), void (*parent)(), + void (*child)()); +}; + +INTERCEPTOR(int, pthread_atfork, void (*prepare)(), void (*parent)(), + void (*child)()) { +#if CAN_SANITIZE_LEAKS + __lsan::ScopedInterceptorDisabler disabler; +#endif + // REAL(pthread_atfork) cannot be called due to symbol indirections at least on NetBSD + return _pthread_atfork(prepare, parent, child); +} +#endif + #if ASAN_INTERCEPT_VFORK DEFINE_REAL(int, vfork) DECLARE_EXTERN_INTERCEPTOR_AND_WRAPPER(int, vfork) @@ -660,6 +694,14 @@ void InitializeAsanInterceptors() { ASAN_INTERCEPT_FUNC(__cxa_atexit); #endif +#if ASAN_INTERCEPT_ATEXIT + ASAN_INTERCEPT_FUNC(atexit); +#endif + +#if ASAN_INTERCEPT_PTHREAD_ATFORK + ASAN_INTERCEPT_FUNC(pthread_atfork); +#endif + #if ASAN_INTERCEPT_VFORK ASAN_INTERCEPT_FUNC(vfork); #endif diff --git a/lib/asan/asan_interceptors.h b/lib/asan/asan_interceptors.h index 155ea4156..344a64bd8 100644 --- a/lib/asan/asan_interceptors.h +++ b/lib/asan/asan_interceptors.h @@ -99,6 +99,12 @@ void InitializePlatformInterceptors(); # define ASAN_INTERCEPT___CXA_ATEXIT 0 #endif +#if SANITIZER_NETBSD +# define ASAN_INTERCEPT_ATEXIT 1 +#else +# define ASAN_INTERCEPT_ATEXIT 0 +#endif + #if SANITIZER_LINUX && !SANITIZER_ANDROID # define ASAN_INTERCEPT___STRDUP 1 #else @@ -112,6 +118,12 @@ void InitializePlatformInterceptors(); # define ASAN_INTERCEPT_VFORK 0 #endif +#if SANITIZER_NETBSD +# define ASAN_INTERCEPT_PTHREAD_ATFORK 1 +#else +# define ASAN_INTERCEPT_PTHREAD_ATFORK 0 +#endif + DECLARE_REAL(int, memcmp, const void *a1, const void *a2, uptr size) DECLARE_REAL(char*, strchr, const char *str, int c) DECLARE_REAL(SIZE_T, strlen, const char *s) diff --git a/lib/lsan/lsan_interceptors.cpp b/lib/lsan/lsan_interceptors.cpp index f06d5fff7..84a6acda4 100644 --- a/lib/lsan/lsan_interceptors.cpp +++ b/lib/lsan/lsan_interceptors.cpp @@ -345,6 +345,44 @@ INTERCEPTOR(void, thr_exit, tid_t *state) { #define LSAN_MAYBE_INTERCEPT_THR_EXIT #endif +#if SANITIZER_INTERCEPT___CXA_ATEXIT +INTERCEPTOR(int, __cxa_atexit, void (*func)(void *), void *arg, + void *dso_handle) { + __lsan::ScopedInterceptorDisabler disabler; + return REAL(__cxa_atexit)(func, arg, dso_handle); +} +#define LSAN_MAYBE_INTERCEPT___CXA_ATEXIT INTERCEPT_FUNCTION(__cxa_atexit) +#else +#define LSAN_MAYBE_INTERCEPT___CXA_ATEXIT +#endif + +#if SANITIZER_INTERCEPT_ATEXIT +INTERCEPTOR(int, atexit, void (*f)()) { + __lsan::ScopedInterceptorDisabler disabler; + return REAL(__cxa_atexit)((void (*)(void *a))f, 0, 0); +} +#define LSAN_MAYBE_INTERCEPT_ATEXIT INTERCEPT_FUNCTION(atexit) +#else +#define LSAN_MAYBE_INTERCEPT_ATEXIT +#endif + +#if SANITIZER_INTERCEPT_PTHREAD_ATFORK +extern "C" { +extern int _pthread_atfork(void (*prepare)(), void (*parent)(), + void (*child)()); +}; + +INTERCEPTOR(int, pthread_atfork, void (*prepare)(), void (*parent)(), + void (*child)()) { + __lsan::ScopedInterceptorDisabler disabler; + // REAL(pthread_atfork) cannot be called due to symbol indirections at least on NetBSD + return _pthread_atfork(prepare, parent, child); +} +#define LSAN_MAYBE_INTERCEPT_PTHREAD_ATFORK INTERCEPT_FUNCTION(pthread_atfork) +#else +#define LSAN_MAYBE_INTERCEPT_PTHREAD_ATFORK +#endif + struct ThreadParam { void *(*callback)(void *arg); void *param; @@ -454,6 +492,10 @@ void InitializeInterceptors() { LSAN_MAYBE_INTERCEPT__LWP_EXIT; LSAN_MAYBE_INTERCEPT_THR_EXIT; + LSAN_MAYBE_INTERCEPT___CXA_ATEXIT; + LSAN_MAYBE_INTERCEPT_ATEXIT; + LSAN_MAYBE_INTERCEPT_PTHREAD_ATFORK; + #if !SANITIZER_NETBSD && !SANITIZER_FREEBSD if (pthread_key_create(&g_thread_finalize_key, &thread_finalize)) { Report("LeakSanitizer: failed to create thread key.\n"); diff --git a/lib/sanitizer_common/sanitizer_platform_interceptors.h b/lib/sanitizer_common/sanitizer_platform_interceptors.h index cf079c435..c3b6f2855 100644 --- a/lib/sanitizer_common/sanitizer_platform_interceptors.h +++ b/lib/sanitizer_common/sanitizer_platform_interceptors.h @@ -567,5 +567,9 @@ #define SANITIZER_INTERCEPT_SL_INIT (SI_FREEBSD || SI_NETBSD) #define SANITIZER_INTERCEPT_GETRANDOM SI_LINUX +#define SANITIZER_INTERCEPT___CXA_ATEXIT SI_NETBSD +#define SANITIZER_INTERCEPT_ATEXIT SI_NETBSD +#define SANITIZER_INTERCEPT_PTHREAD_ATFORK SI_NETBSD + #endif // #ifndef SANITIZER_PLATFORM_INTERCEPTORS_H |