diff options
author | Vitaly Buka <vitalybuka@google.com> | 2017-11-20 23:37:46 +0000 |
---|---|---|
committer | Vitaly Buka <vitalybuka@google.com> | 2017-11-20 23:37:46 +0000 |
commit | 425a276f1ad02b7e08a41d667475838e848b5a53 (patch) | |
tree | ce111fffbcb0ab12173dd4268b9338eda1c13d8f /lib | |
parent | c3efd8d451dc3d8d2c932cf8082c26ed1be0629d (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.cc | 52 |
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) { |