Skip to content

Commit 7f6bb4a

Browse files
committedNov 20, 2017
[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 llvm-svn: 318707
1 parent 67eb30a commit 7f6bb4a

File tree

2 files changed

+39
-28
lines changed

2 files changed

+39
-28
lines changed
 

‎compiler-rt/lib/tsan/rtl/tsan_interceptors.cc

+27-25
Original file line numberDiff line numberDiff line change
@@ -2287,33 +2287,35 @@ int sigaction_impl(int sig, const __sanitizer_sigaction *act,
22872287
SCOPED_INTERCEPTOR_RAW(sigaction, sig, act, old);
22882288
__sanitizer_sigaction *sigactions = interceptor_ctx()->sigactions;
22892289
__sanitizer_sigaction old_stored;
2290-
internal_memcpy(&old_stored, &sigactions[sig], sizeof(old_stored));
2291-
if (act == 0) return 0;
2292-
// Copy act into sigactions[sig].
2293-
// Can't use struct copy, because compiler can emit call to memcpy.
2294-
// Can't use internal_memcpy, because it copies byte-by-byte,
2295-
// and signal handler reads the handler concurrently. It it can read
2296-
// some bytes from old value and some bytes from new value.
2297-
// Use volatile to prevent insertion of memcpy.
2298-
sigactions[sig].handler =
2299-
*(volatile __sanitizer_sighandler_ptr const *)&act->handler;
2300-
sigactions[sig].sa_flags = *(volatile int const *)&act->sa_flags;
2301-
internal_memcpy(&sigactions[sig].sa_mask, &act->sa_mask,
2302-
sizeof(sigactions[sig].sa_mask));
2303-
#if !SANITIZER_FREEBSD && !SANITIZER_MAC && !SANITIZER_NETBSD
2304-
sigactions[sig].sa_restorer = act->sa_restorer;
2305-
#endif
2290+
if (old) internal_memcpy(&old_stored, &sigactions[sig], sizeof(old_stored));
23062291
__sanitizer_sigaction newact;
2307-
internal_memcpy(&newact, act, sizeof(newact));
2308-
internal_sigfillset(&newact.sa_mask);
2309-
if ((uptr)act->handler != sig_ign && (uptr)act->handler != sig_dfl) {
2310-
if (newact.sa_flags & SA_SIGINFO)
2311-
newact.sigaction = rtl_sigaction;
2312-
else
2313-
newact.handler = rtl_sighandler;
2292+
if (act) {
2293+
// Copy act into sigactions[sig].
2294+
// Can't use struct copy, because compiler can emit call to memcpy.
2295+
// Can't use internal_memcpy, because it copies byte-by-byte,
2296+
// and signal handler reads the handler concurrently. It it can read
2297+
// some bytes from old value and some bytes from new value.
2298+
// Use volatile to prevent insertion of memcpy.
2299+
sigactions[sig].handler =
2300+
*(volatile __sanitizer_sighandler_ptr const *)&act->handler;
2301+
sigactions[sig].sa_flags = *(volatile int const *)&act->sa_flags;
2302+
internal_memcpy(&sigactions[sig].sa_mask, &act->sa_mask,
2303+
sizeof(sigactions[sig].sa_mask));
2304+
#if !SANITIZER_FREEBSD && !SANITIZER_MAC && !SANITIZER_NETBSD
2305+
sigactions[sig].sa_restorer = act->sa_restorer;
2306+
#endif
2307+
internal_memcpy(&newact, act, sizeof(newact));
2308+
internal_sigfillset(&newact.sa_mask);
2309+
if ((uptr)act->handler != sig_ign && (uptr)act->handler != sig_dfl) {
2310+
if (newact.sa_flags & SA_SIGINFO)
2311+
newact.sigaction = rtl_sigaction;
2312+
else
2313+
newact.handler = rtl_sighandler;
2314+
}
2315+
ReleaseStore(thr, pc, (uptr)&sigactions[sig]);
2316+
act = &newact;
23142317
}
2315-
ReleaseStore(thr, pc, (uptr)&sigactions[sig]);
2316-
int res = REAL(sigaction)(sig, &newact, old);
2318+
int res = REAL(sigaction)(sig, act, old);
23172319
if (res == 0 && old) {
23182320
uptr cb = (uptr)old->sigaction;
23192321
if (cb == (uptr)rtl_sigaction || cb == (uptr)rtl_sighandler) {

‎compiler-rt/test/sanitizer_common/TestCases/Linux/signal_segv_handler.cc

+12-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
// RUN: %clangxx -O1 %s -o %t && TSAN_OPTIONS="flush_memory_ms=1 memory_limit_mb=1" ASAN_OPTIONS="handle_segv=0" %run %t 2>&1 | FileCheck %s
1+
// clang-format off
2+
// RUN: %clangxx -O1 %s -o %t && TSAN_OPTIONS="flush_memory_ms=1 memory_limit_mb=1" %run %t 2>&1 | FileCheck %s
3+
// clang-format on
24

35
// JVM uses SEGV to preempt threads. All threads do a load from a known address
46
// periodically. When runtime needs to preempt threads, it unmaps the page.
@@ -13,11 +15,12 @@
1315
// "benign" SEGVs that are handled by signal handler, and ensures that
1416
// the process survive.
1517

18+
#include <assert.h>
19+
#include <signal.h>
1620
#include <stdio.h>
1721
#include <stdlib.h>
18-
#include <signal.h>
19-
#include <sys/mman.h>
2022
#include <string.h>
23+
#include <sys/mman.h>
2124
#include <unistd.h>
2225

2326
unsigned long page_size;
@@ -35,6 +38,12 @@ int main() {
3538
a.sa_sigaction = handler;
3639
a.sa_flags = SA_SIGINFO;
3740
sigaction(SIGSEGV, &a, &old);
41+
42+
memset(&a, 0, sizeof(a));
43+
sigaction(SIGSEGV, 0, &a);
44+
assert(a.sa_sigaction == handler);
45+
assert(a.sa_flags & SA_SIGINFO);
46+
3847
guard = mmap(0, 3 * page_size, PROT_NONE, MAP_ANON | MAP_PRIVATE, -1, 0);
3948
guard = (char*)guard + page_size; // work around a kernel bug
4049
for (int i = 0; i < 1000000; i++) {

0 commit comments

Comments
 (0)
Please sign in to comment.