From fb32a69855341630a7084364c66083264e1d18bf Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Wed, 4 Jan 2023 12:04:19 -0800 Subject: [PATCH] [sanitizer] Move {,__}pthread_mutex_{lock,unlock} interceptors to tsan These interceptors are pure forwarders for other sanitizers. Move them beside tsan-specific pthread_mutex_{trylock,timedlock} interceptors. While here, guard `__pthread_mutex_{lock,unlock}` (D46793) under `#if !__GLIBC_PREREQ(2, 34)`. In glibc>=2.34 [1], `__pthread_mutex_{lock,unlock}` only have non-default-version definitions (unversioned `__pthread_mutex_lock` causes a linker error. Program preloading is not expected). In glibc>=2.36 [2], `dlsym(RTLD_NEXT, "__pthread_mutex_lock")` returns nullptr, so the interceptor won't work. Fix https://github.com/llvm/llvm-project/issues/59820 [1]: https://sourceware.org/git/?p=glibc.git;a=commit;h=99f841c441feeaa9a3d97fd91bb3d6ec8073c982 [2]: https://sourceware.org/git/?p=glibc.git;a=commit;h=efa7936e4c91b1c260d03614bb26858fbb8a0204 Reviewed By: melver, vitalybuka Differential Revision: https://reviews.llvm.org/D140957 --- .../sanitizer_common_interceptors.inc | 107 --------------------- .../sanitizer_platform_interceptors.h | 2 - .../lib/tsan/rtl-old/tsan_interceptors_posix.cpp | 44 +++++---- .../lib/tsan/rtl/tsan_interceptors_posix.cpp | 82 ++++++++++++---- 4 files changed, 86 insertions(+), 149 deletions(-) diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc index ba4b800..e50bc87 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors.inc @@ -23,10 +23,6 @@ // COMMON_INTERCEPTOR_SET_THREAD_NAME // COMMON_INTERCEPTOR_DLOPEN // COMMON_INTERCEPTOR_ON_EXIT -// COMMON_INTERCEPTOR_MUTEX_PRE_LOCK -// COMMON_INTERCEPTOR_MUTEX_POST_LOCK -// COMMON_INTERCEPTOR_MUTEX_UNLOCK -// COMMON_INTERCEPTOR_MUTEX_REPAIR // COMMON_INTERCEPTOR_SET_PTHREAD_NAME // COMMON_INTERCEPTOR_HANDLE_RECVMSG // COMMON_INTERCEPTOR_NOTHING_IS_INITIALIZED @@ -223,26 +219,6 @@ extern const short *_tolower_tab_; #define COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd) {} #endif -#ifndef COMMON_INTERCEPTOR_MUTEX_PRE_LOCK -#define COMMON_INTERCEPTOR_MUTEX_PRE_LOCK(ctx, m) {} -#endif - -#ifndef COMMON_INTERCEPTOR_MUTEX_POST_LOCK -#define COMMON_INTERCEPTOR_MUTEX_POST_LOCK(ctx, m) {} -#endif - -#ifndef COMMON_INTERCEPTOR_MUTEX_UNLOCK -#define COMMON_INTERCEPTOR_MUTEX_UNLOCK(ctx, m) {} -#endif - -#ifndef COMMON_INTERCEPTOR_MUTEX_REPAIR -#define COMMON_INTERCEPTOR_MUTEX_REPAIR(ctx, m) {} -#endif - -#ifndef COMMON_INTERCEPTOR_MUTEX_INVALID -#define COMMON_INTERCEPTOR_MUTEX_INVALID(ctx, m) {} -#endif - #ifndef COMMON_INTERCEPTOR_HANDLE_RECVMSG #define COMMON_INTERCEPTOR_HANDLE_RECVMSG(ctx, msg) ((void)(msg)) #endif @@ -4475,90 +4451,13 @@ INTERCEPTOR(void, _exit, int status) { #define INIT__EXIT #endif -#if SANITIZER_INTERCEPT_PTHREAD_MUTEX -INTERCEPTOR(int, pthread_mutex_lock, void *m) { - void *ctx; - COMMON_INTERCEPTOR_ENTER(ctx, pthread_mutex_lock, m); - COMMON_INTERCEPTOR_MUTEX_PRE_LOCK(ctx, m); - int res = REAL(pthread_mutex_lock)(m); - if (res == errno_EOWNERDEAD) - COMMON_INTERCEPTOR_MUTEX_REPAIR(ctx, m); - if (res == 0 || res == errno_EOWNERDEAD) - COMMON_INTERCEPTOR_MUTEX_POST_LOCK(ctx, m); - if (res == errno_EINVAL) - COMMON_INTERCEPTOR_MUTEX_INVALID(ctx, m); - return res; -} - -INTERCEPTOR(int, pthread_mutex_unlock, void *m) { - void *ctx; - COMMON_INTERCEPTOR_ENTER(ctx, pthread_mutex_unlock, m); - COMMON_INTERCEPTOR_MUTEX_UNLOCK(ctx, m); - int res = REAL(pthread_mutex_unlock)(m); - if (res == errno_EINVAL) - COMMON_INTERCEPTOR_MUTEX_INVALID(ctx, m); - return res; -} - -#define INIT_PTHREAD_MUTEX_LOCK COMMON_INTERCEPT_FUNCTION(pthread_mutex_lock) -#define INIT_PTHREAD_MUTEX_UNLOCK \ - COMMON_INTERCEPT_FUNCTION(pthread_mutex_unlock) -#else -#define INIT_PTHREAD_MUTEX_LOCK -#define INIT_PTHREAD_MUTEX_UNLOCK -#endif - -#if SANITIZER_INTERCEPT___PTHREAD_MUTEX -INTERCEPTOR(int, __pthread_mutex_lock, void *m) { - void *ctx; - COMMON_INTERCEPTOR_ENTER(ctx, __pthread_mutex_lock, m); - COMMON_INTERCEPTOR_MUTEX_PRE_LOCK(ctx, m); - int res = REAL(__pthread_mutex_lock)(m); - if (res == errno_EOWNERDEAD) - COMMON_INTERCEPTOR_MUTEX_REPAIR(ctx, m); - if (res == 0 || res == errno_EOWNERDEAD) - COMMON_INTERCEPTOR_MUTEX_POST_LOCK(ctx, m); - if (res == errno_EINVAL) - COMMON_INTERCEPTOR_MUTEX_INVALID(ctx, m); - return res; -} - -INTERCEPTOR(int, __pthread_mutex_unlock, void *m) { - void *ctx; - COMMON_INTERCEPTOR_ENTER(ctx, __pthread_mutex_unlock, m); - COMMON_INTERCEPTOR_MUTEX_UNLOCK(ctx, m); - int res = REAL(__pthread_mutex_unlock)(m); - if (res == errno_EINVAL) - COMMON_INTERCEPTOR_MUTEX_INVALID(ctx, m); - return res; -} - -#define INIT___PTHREAD_MUTEX_LOCK \ - COMMON_INTERCEPT_FUNCTION(__pthread_mutex_lock) -#define INIT___PTHREAD_MUTEX_UNLOCK \ - COMMON_INTERCEPT_FUNCTION(__pthread_mutex_unlock) -#else -#define INIT___PTHREAD_MUTEX_LOCK -#define INIT___PTHREAD_MUTEX_UNLOCK -#endif - #if SANITIZER_INTERCEPT___LIBC_MUTEX -INTERCEPTOR(int, __libc_mutex_lock, void *m) -ALIAS(WRAPPER_NAME(pthread_mutex_lock)); - -INTERCEPTOR(int, __libc_mutex_unlock, void *m) -ALIAS(WRAPPER_NAME(pthread_mutex_unlock)); - INTERCEPTOR(int, __libc_thr_setcancelstate, int state, int *oldstate) ALIAS(WRAPPER_NAME(pthread_setcancelstate)); -#define INIT___LIBC_MUTEX_LOCK COMMON_INTERCEPT_FUNCTION(__libc_mutex_lock) -#define INIT___LIBC_MUTEX_UNLOCK COMMON_INTERCEPT_FUNCTION(__libc_mutex_unlock) #define INIT___LIBC_THR_SETCANCELSTATE \ COMMON_INTERCEPT_FUNCTION(__libc_thr_setcancelstate) #else -#define INIT___LIBC_MUTEX_LOCK -#define INIT___LIBC_MUTEX_UNLOCK #define INIT___LIBC_THR_SETCANCELSTATE #endif @@ -10604,12 +10503,6 @@ static void InitializeCommonInterceptors() { INIT_PTHREAD_SIGMASK; INIT_BACKTRACE; INIT__EXIT; - INIT_PTHREAD_MUTEX_LOCK; - INIT_PTHREAD_MUTEX_UNLOCK; - INIT___PTHREAD_MUTEX_LOCK; - INIT___PTHREAD_MUTEX_UNLOCK; - INIT___LIBC_MUTEX_LOCK; - INIT___LIBC_MUTEX_UNLOCK; INIT___LIBC_THR_SETCANCELSTATE; INIT_GETMNTENT; INIT_GETMNTENT_R; diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h b/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h index 7b82c3d..7d61af6 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h @@ -396,8 +396,6 @@ #define SANITIZER_INTERCEPT__EXIT \ (SI_LINUX || SI_FREEBSD || SI_NETBSD || SI_MAC || SI_SOLARIS) -#define SANITIZER_INTERCEPT_PTHREAD_MUTEX SI_POSIX -#define SANITIZER_INTERCEPT___PTHREAD_MUTEX SI_GLIBC #define SANITIZER_INTERCEPT___LIBC_MUTEX SI_NETBSD #define SANITIZER_INTERCEPT_PTHREAD_SETNAME_NP \ (SI_FREEBSD || SI_NETBSD || SI_GLIBC || SI_SOLARIS) diff --git a/compiler-rt/lib/tsan/rtl-old/tsan_interceptors_posix.cpp b/compiler-rt/lib/tsan/rtl-old/tsan_interceptors_posix.cpp index 61204f9..96ae599 100644 --- a/compiler-rt/lib/tsan/rtl-old/tsan_interceptors_posix.cpp +++ b/compiler-rt/lib/tsan/rtl-old/tsan_interceptors_posix.cpp @@ -1333,6 +1333,19 @@ TSAN_INTERCEPTOR(int, pthread_mutex_destroy, void *m) { return res; } +TSAN_INTERCEPTOR(int, pthread_mutex_lock, void *m) { + SCOPED_TSAN_INTERCEPTOR(pthread_mutex_lock, m); + MutexPreLock(thr, pc, (uptr)m); + int res = REAL(pthread_mutex_lock)(m); + if (res == errno_EOWNERDEAD) + MutexRepair(thr, pc, (uptr)m); + if (res == 0 || res == errno_EOWNERDEAD) + MutexPostLock(thr, pc, (uptr)m); + if (res == errno_EINVAL) + MutexInvalidAccess(thr, pc, (uptr)m); + return res; +} + TSAN_INTERCEPTOR(int, pthread_mutex_trylock, void *m) { SCOPED_TSAN_INTERCEPTOR(pthread_mutex_trylock, m); int res = REAL(pthread_mutex_trylock)(m); @@ -1354,6 +1367,15 @@ TSAN_INTERCEPTOR(int, pthread_mutex_timedlock, void *m, void *abstime) { } #endif +TSAN_INTERCEPTOR(int, pthread_mutex_unlock, void *m) { + SCOPED_TSAN_INTERCEPTOR(pthread_mutex_unlock, m); + MutexUnlock(thr, pc, (uptr)m); + int res = REAL(pthread_mutex_unlock)(m); + if (res == errno_EINVAL) + MutexInvalidAccess(thr, pc, (uptr)m); + return res; +} + #if !SANITIZER_APPLE TSAN_INTERCEPTOR(int, pthread_spin_init, void *m, int pshared) { SCOPED_TSAN_INTERCEPTOR(pthread_spin_init, m, pshared); @@ -2427,26 +2449,6 @@ static void HandleRecvmsg(ThreadState *thr, uptr pc, #define COMMON_INTERCEPTOR_ON_EXIT(ctx) \ OnExit(((TsanInterceptorContext *) ctx)->thr) -#define COMMON_INTERCEPTOR_MUTEX_PRE_LOCK(ctx, m) \ - MutexPreLock(((TsanInterceptorContext *)ctx)->thr, \ - ((TsanInterceptorContext *)ctx)->pc, (uptr)m) - -#define COMMON_INTERCEPTOR_MUTEX_POST_LOCK(ctx, m) \ - MutexPostLock(((TsanInterceptorContext *)ctx)->thr, \ - ((TsanInterceptorContext *)ctx)->pc, (uptr)m) - -#define COMMON_INTERCEPTOR_MUTEX_UNLOCK(ctx, m) \ - MutexUnlock(((TsanInterceptorContext *)ctx)->thr, \ - ((TsanInterceptorContext *)ctx)->pc, (uptr)m) - -#define COMMON_INTERCEPTOR_MUTEX_REPAIR(ctx, m) \ - MutexRepair(((TsanInterceptorContext *)ctx)->thr, \ - ((TsanInterceptorContext *)ctx)->pc, (uptr)m) - -#define COMMON_INTERCEPTOR_MUTEX_INVALID(ctx, m) \ - MutexInvalidAccess(((TsanInterceptorContext *)ctx)->thr, \ - ((TsanInterceptorContext *)ctx)->pc, (uptr)m) - #define COMMON_INTERCEPTOR_MMAP_IMPL(ctx, mmap, addr, sz, prot, flags, fd, \ off) \ do { \ @@ -2825,8 +2827,10 @@ void InitializeInterceptors() { TSAN_INTERCEPT(pthread_mutex_init); TSAN_INTERCEPT(pthread_mutex_destroy); + TSAN_INTERCEPT(pthread_mutex_lock); TSAN_INTERCEPT(pthread_mutex_trylock); TSAN_INTERCEPT(pthread_mutex_timedlock); + TSAN_INTERCEPT(pthread_mutex_unlock); TSAN_INTERCEPT(pthread_spin_init); TSAN_INTERCEPT(pthread_spin_destroy); diff --git a/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp b/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp index a4bd5ba..cb28e74 100644 --- a/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp +++ b/compiler-rt/lib/tsan/rtl/tsan_interceptors_posix.cpp @@ -1353,6 +1353,19 @@ TSAN_INTERCEPTOR(int, pthread_mutex_destroy, void *m) { return res; } +TSAN_INTERCEPTOR(int, pthread_mutex_lock, void *m) { + SCOPED_TSAN_INTERCEPTOR(pthread_mutex_lock, m); + MutexPreLock(thr, pc, (uptr)m); + int res = REAL(pthread_mutex_lock)(m); + if (res == errno_EOWNERDEAD) + MutexRepair(thr, pc, (uptr)m); + if (res == 0 || res == errno_EOWNERDEAD) + MutexPostLock(thr, pc, (uptr)m); + if (res == errno_EINVAL) + MutexInvalidAccess(thr, pc, (uptr)m); + return res; +} + TSAN_INTERCEPTOR(int, pthread_mutex_trylock, void *m) { SCOPED_TSAN_INTERCEPTOR(pthread_mutex_trylock, m); int res = REAL(pthread_mutex_trylock)(m); @@ -1374,6 +1387,43 @@ TSAN_INTERCEPTOR(int, pthread_mutex_timedlock, void *m, void *abstime) { } #endif +TSAN_INTERCEPTOR(int, pthread_mutex_unlock, void *m) { + SCOPED_TSAN_INTERCEPTOR(pthread_mutex_unlock, m); + MutexUnlock(thr, pc, (uptr)m); + int res = REAL(pthread_mutex_unlock)(m); + if (res == errno_EINVAL) + MutexInvalidAccess(thr, pc, (uptr)m); + return res; +} + +#if SANITIZER_GLIBC +# if !__GLIBC_PREREQ(2, 34) +// glibc 2.34 applies a non-default version for the two functions. They are no +// longer expected to be intercepted by programs. +TSAN_INTERCEPTOR(int, __pthread_mutex_lock, void *m) { + SCOPED_TSAN_INTERCEPTOR(__pthread_mutex_lock, m); + MutexPreLock(thr, pc, (uptr)m); + int res = REAL(__pthread_mutex_lock)(m); + if (res == errno_EOWNERDEAD) + MutexRepair(thr, pc, (uptr)m); + if (res == 0 || res == errno_EOWNERDEAD) + MutexPostLock(thr, pc, (uptr)m); + if (res == errno_EINVAL) + MutexInvalidAccess(thr, pc, (uptr)m); + return res; +} + +TSAN_INTERCEPTOR(int, __pthread_mutex_unlock, void *m) { + SCOPED_TSAN_INTERCEPTOR(__pthread_mutex_unlock, m); + MutexUnlock(thr, pc, (uptr)m); + int res = REAL(__pthread_mutex_unlock)(m); + if (res == errno_EINVAL) + MutexInvalidAccess(thr, pc, (uptr)m); + return res; +} +# endif +#endif + #if !SANITIZER_APPLE TSAN_INTERCEPTOR(int, pthread_spin_init, void *m, int pshared) { SCOPED_TSAN_INTERCEPTOR(pthread_spin_init, m, pshared); @@ -2470,26 +2520,6 @@ static void HandleRecvmsg(ThreadState *thr, uptr pc, #define COMMON_INTERCEPTOR_ON_EXIT(ctx) \ OnExit(((TsanInterceptorContext *) ctx)->thr) -#define COMMON_INTERCEPTOR_MUTEX_PRE_LOCK(ctx, m) \ - MutexPreLock(((TsanInterceptorContext *)ctx)->thr, \ - ((TsanInterceptorContext *)ctx)->pc, (uptr)m) - -#define COMMON_INTERCEPTOR_MUTEX_POST_LOCK(ctx, m) \ - MutexPostLock(((TsanInterceptorContext *)ctx)->thr, \ - ((TsanInterceptorContext *)ctx)->pc, (uptr)m) - -#define COMMON_INTERCEPTOR_MUTEX_UNLOCK(ctx, m) \ - MutexUnlock(((TsanInterceptorContext *)ctx)->thr, \ - ((TsanInterceptorContext *)ctx)->pc, (uptr)m) - -#define COMMON_INTERCEPTOR_MUTEX_REPAIR(ctx, m) \ - MutexRepair(((TsanInterceptorContext *)ctx)->thr, \ - ((TsanInterceptorContext *)ctx)->pc, (uptr)m) - -#define COMMON_INTERCEPTOR_MUTEX_INVALID(ctx, m) \ - MutexInvalidAccess(((TsanInterceptorContext *)ctx)->thr, \ - ((TsanInterceptorContext *)ctx)->pc, (uptr)m) - #define COMMON_INTERCEPTOR_MMAP_IMPL(ctx, mmap, addr, sz, prot, flags, fd, \ off) \ do { \ @@ -2786,7 +2816,9 @@ TSAN_INTERCEPTOR_NETBSD_ALIAS(int, cond_wait, void *c, void *m) TSAN_INTERCEPTOR_NETBSD_ALIAS(int, cond_destroy, void *c) TSAN_INTERCEPTOR_NETBSD_ALIAS(int, mutex_init, void *m, void *a) TSAN_INTERCEPTOR_NETBSD_ALIAS(int, mutex_destroy, void *m) +TSAN_INTERCEPTOR_NETBSD_ALIAS(int, mutex_lock, void *m) TSAN_INTERCEPTOR_NETBSD_ALIAS(int, mutex_trylock, void *m) +TSAN_INTERCEPTOR_NETBSD_ALIAS(int, mutex_unlock, void *m) TSAN_INTERCEPTOR_NETBSD_ALIAS(int, rwlock_init, void *m, void *a) TSAN_INTERCEPTOR_NETBSD_ALIAS(int, rwlock_destroy, void *m) TSAN_INTERCEPTOR_NETBSD_ALIAS(int, rwlock_rdlock, void *m) @@ -2888,8 +2920,16 @@ void InitializeInterceptors() { TSAN_INTERCEPT(pthread_mutex_init); TSAN_INTERCEPT(pthread_mutex_destroy); + TSAN_INTERCEPT(pthread_mutex_lock); TSAN_INTERCEPT(pthread_mutex_trylock); TSAN_INTERCEPT(pthread_mutex_timedlock); + TSAN_INTERCEPT(pthread_mutex_unlock); +#if SANITIZER_GLIBC +# if !__GLIBC_PREREQ(2, 34) + TSAN_INTERCEPT(__pthread_mutex_lock); + TSAN_INTERCEPT(__pthread_mutex_unlock); +# endif +#endif TSAN_INTERCEPT(pthread_spin_init); TSAN_INTERCEPT(pthread_spin_destroy); @@ -3034,7 +3074,9 @@ void InitializeInterceptors() { TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS(cond_destroy); TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS(mutex_init); TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS(mutex_destroy); + TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS(mutex_lock); TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS(mutex_trylock); + TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS(mutex_unlock); TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS(rwlock_init); TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS(rwlock_destroy); TSAN_MAYBE_INTERCEPT_NETBSD_ALIAS(rwlock_rdlock); -- 2.7.4