diff options
author | Evgeniy Stepanov <eugeni.stepanov@gmail.com> | 2013-08-27 11:34:05 +0000 |
---|---|---|
committer | Evgeniy Stepanov <eugeni.stepanov@gmail.com> | 2013-08-27 11:34:05 +0000 |
commit | e0a871284c7496b91add2956531d1a9e65b7bc88 (patch) | |
tree | 47c402ab1c92d86c98c917178c3a80ce6433098e /lib/msan/msan_interceptors.cc | |
parent | 47177efc15d2a75c7c85ba31aa61e41e7b47b5a3 (diff) | |
download | compiler-rt-e0a871284c7496b91add2956531d1a9e65b7bc88.tar.gz compiler-rt-e0a871284c7496b91add2956531d1a9e65b7bc88.tar.bz2 compiler-rt-e0a871284c7496b91add2956531d1a9e65b7bc88.tar.xz |
[msan] Fix a data race in signal/sigaction interceptors.
git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@189342 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/msan/msan_interceptors.cc')
-rw-r--r-- | lib/msan/msan_interceptors.cc | 23 |
1 files changed, 17 insertions, 6 deletions
diff --git a/lib/msan/msan_interceptors.cc b/lib/msan/msan_interceptors.cc index 6d511179..5e89ef54 100644 --- a/lib/msan/msan_interceptors.cc +++ b/lib/msan/msan_interceptors.cc @@ -19,6 +19,7 @@ #include "msan.h" #include "sanitizer_common/sanitizer_platform_limits_posix.h" #include "sanitizer_common/sanitizer_allocator.h" +#include "sanitizer_common/sanitizer_atomic.h" #include "sanitizer_common/sanitizer_common.h" #include "sanitizer_common/sanitizer_stackdepot.h" #include "sanitizer_common/sanitizer_libc.h" @@ -30,6 +31,11 @@ using namespace __msan; +using __sanitizer::memory_order; +using __sanitizer::atomic_load; +using __sanitizer::atomic_store; +using __sanitizer::atomic_uintptr_t; + // True if this is a nested interceptor. static THREADLOCAL int in_interceptor_scope; @@ -897,13 +903,17 @@ INTERCEPTOR(int, getrusage, int who, void *usage) { return res; } +// sigactions_mu guarantees atomicity of sigaction() and signal() calls. +// Access to sigactions[] is gone with relaxed atomics to avoid data race with +// the signal handler. const int kMaxSignals = 1024; -static uptr sigactions[kMaxSignals]; +static atomic_uintptr_t sigactions[kMaxSignals]; static StaticSpinMutex sigactions_mu; static void SignalHandler(int signo) { typedef void (*signal_cb)(int x); - signal_cb cb = (signal_cb)sigactions[signo]; + signal_cb cb = + (signal_cb)atomic_load(&sigactions[signo], memory_order_relaxed); cb(signo); } @@ -913,7 +923,8 @@ static void SignalAction(int signo, void *si, void *uc) { __msan_unpoison(uc, __sanitizer::ucontext_t_sz); typedef void (*sigaction_cb)(int, void *, void *); - sigaction_cb cb = (sigaction_cb)sigactions[signo]; + sigaction_cb cb = + (sigaction_cb)atomic_load(&sigactions[signo], memory_order_relaxed); cb(signo, si, uc); } @@ -926,7 +937,7 @@ INTERCEPTOR(int, sigaction, int signo, const __sanitizer_sigaction *act, if (flags()->wrap_signals) { SpinMutexLock lock(&sigactions_mu); CHECK_LT(signo, kMaxSignals); - uptr old_cb = sigactions[signo]; + uptr old_cb = atomic_load(&sigactions[signo], memory_order_relaxed); __sanitizer_sigaction new_act; __sanitizer_sigaction *pnew_act = act ? &new_act : 0; if (act) { @@ -936,7 +947,7 @@ INTERCEPTOR(int, sigaction, int signo, const __sanitizer_sigaction *act, ? (uptr)SignalAction : (uptr)SignalHandler; if (cb != __sanitizer::sig_ign && cb != __sanitizer::sig_dfl) { - sigactions[signo] = cb; + atomic_store(&sigactions[signo], cb, memory_order_relaxed); pnew_act->sa_sigaction = (void (*)(int, void *, void *))new_cb; } } @@ -963,7 +974,7 @@ INTERCEPTOR(int, signal, int signo, uptr cb) { CHECK_LT(signo, kMaxSignals); SpinMutexLock lock(&sigactions_mu); if (cb != __sanitizer::sig_ign && cb != __sanitizer::sig_dfl) { - sigactions[signo] = cb; + atomic_store(&sigactions[signo], cb, memory_order_relaxed); cb = (uptr) SignalHandler; } return REAL(signal)(signo, cb); |