[msan] Fix a data race in signal/sigaction interceptors.
llvm-svn: 189342
This commit is contained in:
parent
a710d810f5
commit
bb25af5f7b
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue