summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorVitaly Buka <vitalybuka@google.com>2017-11-20 23:37:46 +0000
committerVitaly Buka <vitalybuka@google.com>2017-11-20 23:37:46 +0000
commit425a276f1ad02b7e08a41d667475838e848b5a53 (patch)
treece111fffbcb0ab12173dd4268b9338eda1c13d8f /lib
parentc3efd8d451dc3d8d2c932cf8082c26ed1be0629d (diff)
[tsan] Fix sigaction implementation when it's called only to get handler
Reviewers: eugenis Subscribers: kubamracek, llvm-commits, krytarowski Differential Revision: https://reviews.llvm.org/D40272 git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@318707 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r--lib/tsan/rtl/tsan_interceptors.cc52
1 files changed, 27 insertions, 25 deletions
diff --git a/lib/tsan/rtl/tsan_interceptors.cc b/lib/tsan/rtl/tsan_interceptors.cc
index 4f59f7911..df8c5e3df 100644
--- a/lib/tsan/rtl/tsan_interceptors.cc
+++ b/lib/tsan/rtl/tsan_interceptors.cc
@@ -2287,33 +2287,35 @@ int sigaction_impl(int sig, const __sanitizer_sigaction *act,
SCOPED_INTERCEPTOR_RAW(sigaction, sig, act, old);
__sanitizer_sigaction *sigactions = interceptor_ctx()->sigactions;
__sanitizer_sigaction old_stored;
- internal_memcpy(&old_stored, &sigactions[sig], sizeof(old_stored));
- 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 __sanitizer_sighandler_ptr const *)&act->handler;
- sigactions[sig].sa_flags = *(volatile int const *)&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
+ if (old) internal_memcpy(&old_stored, &sigactions[sig], sizeof(old_stored));
__sanitizer_sigaction newact;
- internal_memcpy(&newact, act, sizeof(newact));
- internal_sigfillset(&newact.sa_mask);
- if ((uptr)act->handler != sig_ign && (uptr)act->handler != sig_dfl) {
- if (newact.sa_flags & SA_SIGINFO)
- newact.sigaction = rtl_sigaction;
- else
- newact.handler = rtl_sighandler;
+ if (act) {
+ // 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 __sanitizer_sighandler_ptr const *)&act->handler;
+ sigactions[sig].sa_flags = *(volatile int const *)&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
+ internal_memcpy(&newact, act, sizeof(newact));
+ internal_sigfillset(&newact.sa_mask);
+ if ((uptr)act->handler != sig_ign && (uptr)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]);
+ act = &newact;
}
- ReleaseStore(thr, pc, (uptr)&sigactions[sig]);
- int res = REAL(sigaction)(sig, &newact, old);
+ int res = REAL(sigaction)(sig, act, old);
if (res == 0 && old) {
uptr cb = (uptr)old->sigaction;
if (cb == (uptr)rtl_sigaction || cb == (uptr)rtl_sighandler) {