forked from OSchip/llvm-project
[tsan] Move code of sigaction_impl and signal_impl
They need to be after sanitizer_signal_interceptors.inc to use READ function Part of https://github.com/google/sanitizers/issues/637 llvm-svn: 317914
This commit is contained in:
parent
01a7e4ca6b
commit
84d11cac28
|
@ -1959,60 +1959,10 @@ TSAN_INTERCEPTOR(int, sigaction, int sig, __sanitizer_sigaction *act,
|
|||
return sigaction_impl(sig, act, old);
|
||||
}
|
||||
|
||||
int sigaction_impl(int sig, __sanitizer_sigaction *act,
|
||||
__sanitizer_sigaction *old) {
|
||||
// Note: if we call REAL(sigaction) directly for any reason without proxying
|
||||
// the signal handler through rtl_sigaction, very bad things will happen.
|
||||
// The handler will run synchronously and corrupt tsan per-thread state.
|
||||
SCOPED_INTERCEPTOR_RAW(sigaction, sig, act, old);
|
||||
__sanitizer_sigaction *sigactions = interceptor_ctx()->sigactions;
|
||||
if (old)
|
||||
internal_memcpy(old, &sigactions[sig], sizeof(*old));
|
||||
if (act == 0)
|
||||
return 0;
|
||||
// Copy act into sigactions[sig].
|
||||
// Can't use struct copy, because compiler can emit call to memcpy.
|
||||
// Can't use internal_memcpy, because it copies byte-by-byte,
|
||||
// and signal handler reads the handler concurrently. It it can read
|
||||
// some bytes from old value and some bytes from new value.
|
||||
// Use volatile to prevent insertion of memcpy.
|
||||
sigactions[sig].handler = *(volatile sighandler_t *)&act->handler;
|
||||
sigactions[sig].sa_flags = *(volatile int*)&act->sa_flags;
|
||||
internal_memcpy(&sigactions[sig].sa_mask, &act->sa_mask,
|
||||
sizeof(sigactions[sig].sa_mask));
|
||||
#if !SANITIZER_FREEBSD && !SANITIZER_MAC && !SANITIZER_NETBSD
|
||||
sigactions[sig].sa_restorer = act->sa_restorer;
|
||||
#endif
|
||||
__sanitizer_sigaction newact;
|
||||
internal_memcpy(&newact, act, sizeof(newact));
|
||||
internal_sigfillset(&newact.sa_mask);
|
||||
if (act->handler != SIG_IGN && act->handler != SIG_DFL) {
|
||||
if (newact.sa_flags & SA_SIGINFO)
|
||||
newact.sigaction = rtl_sigaction;
|
||||
else
|
||||
newact.handler = rtl_sighandler;
|
||||
}
|
||||
ReleaseStore(thr, pc, (uptr)&sigactions[sig]);
|
||||
int res = REAL(sigaction)(sig, &newact, 0);
|
||||
return res;
|
||||
}
|
||||
|
||||
TSAN_INTERCEPTOR(sighandler_t, signal, int sig, sighandler_t h) {
|
||||
return signal_impl(sig, h);
|
||||
}
|
||||
|
||||
static sighandler_t signal_impl(int sig, sighandler_t h) {
|
||||
__sanitizer_sigaction act;
|
||||
act.handler = h;
|
||||
internal_memset(&act.sa_mask, -1, sizeof(act.sa_mask));
|
||||
act.sa_flags = 0;
|
||||
__sanitizer_sigaction old;
|
||||
int res = sigaction(sig, &act, &old);
|
||||
if (res)
|
||||
return SIG_ERR;
|
||||
return old.handler;
|
||||
}
|
||||
|
||||
TSAN_INTERCEPTOR(int, raise, int sig) {
|
||||
SCOPED_TSAN_INTERCEPTOR(raise, sig);
|
||||
ThreadSignalContext *sctx = SigCtx(thr);
|
||||
|
@ -2326,6 +2276,55 @@ static void HandleRecvmsg(ThreadState *thr, uptr pc,
|
|||
|
||||
#include "sanitizer_common/sanitizer_common_interceptors.inc"
|
||||
|
||||
// TODO(vitalybuka): use sanitizer_signal_interceptors.inc here.
|
||||
|
||||
int sigaction_impl(int sig, __sanitizer_sigaction *act,
|
||||
__sanitizer_sigaction *old) {
|
||||
// Note: if we call REAL(sigaction) directly for any reason without proxying
|
||||
// the signal handler through rtl_sigaction, very bad things will happen.
|
||||
// The handler will run synchronously and corrupt tsan per-thread state.
|
||||
SCOPED_INTERCEPTOR_RAW(sigaction, sig, act, old);
|
||||
__sanitizer_sigaction *sigactions = interceptor_ctx()->sigactions;
|
||||
if (old) internal_memcpy(old, &sigactions[sig], sizeof(*old));
|
||||
if (act == 0) return 0;
|
||||
// Copy act into sigactions[sig].
|
||||
// Can't use struct copy, because compiler can emit call to memcpy.
|
||||
// Can't use internal_memcpy, because it copies byte-by-byte,
|
||||
// and signal handler reads the handler concurrently. It it can read
|
||||
// some bytes from old value and some bytes from new value.
|
||||
// Use volatile to prevent insertion of memcpy.
|
||||
sigactions[sig].handler = *(volatile sighandler_t *)&act->handler;
|
||||
sigactions[sig].sa_flags = *(volatile int *)&act->sa_flags;
|
||||
internal_memcpy(&sigactions[sig].sa_mask, &act->sa_mask,
|
||||
sizeof(sigactions[sig].sa_mask));
|
||||
#if !SANITIZER_FREEBSD && !SANITIZER_MAC && !SANITIZER_NETBSD
|
||||
sigactions[sig].sa_restorer = act->sa_restorer;
|
||||
#endif
|
||||
__sanitizer_sigaction newact;
|
||||
internal_memcpy(&newact, act, sizeof(newact));
|
||||
internal_sigfillset(&newact.sa_mask);
|
||||
if (act->handler != SIG_IGN && act->handler != SIG_DFL) {
|
||||
if (newact.sa_flags & SA_SIGINFO)
|
||||
newact.sigaction = rtl_sigaction;
|
||||
else
|
||||
newact.handler = rtl_sighandler;
|
||||
}
|
||||
ReleaseStore(thr, pc, (uptr)&sigactions[sig]);
|
||||
int res = REAL(sigaction)(sig, &newact, 0);
|
||||
return res;
|
||||
}
|
||||
|
||||
static sighandler_t signal_impl(int sig, sighandler_t h) {
|
||||
__sanitizer_sigaction act;
|
||||
act.handler = h;
|
||||
internal_memset(&act.sa_mask, -1, sizeof(act.sa_mask));
|
||||
act.sa_flags = 0;
|
||||
__sanitizer_sigaction old;
|
||||
int res = sigaction(sig, &act, &old);
|
||||
if (res) return SIG_ERR;
|
||||
return old.handler;
|
||||
}
|
||||
|
||||
#define TSAN_SYSCALL() \
|
||||
ThreadState *thr = cur_thread(); \
|
||||
if (thr->ignore_interceptors) \
|
||||
|
|
Loading…
Reference in New Issue