diff --git a/compiler-rt/lib/dfsan/dfsan_custom.cpp b/compiler-rt/lib/dfsan/dfsan_custom.cpp --- a/compiler-rt/lib/dfsan/dfsan_custom.cpp +++ b/compiler-rt/lib/dfsan/dfsan_custom.cpp @@ -937,6 +937,29 @@ return ret; } +SANITIZER_INTERFACE_ATTRIBUTE +sighandler_t __dfsw_signal(int signum, + void *(*handler_trampoline)(void *, int, dfsan_label, + dfsan_label *), + sighandler_t handler, dfsan_label signum_label, + dfsan_label handler_label, dfsan_label *ret_label) { + CHECK_LT(signum, kMaxSignals); + SignalSpinLocker lock; + uptr old_cb = atomic_load(&sigactions[signum], memory_order_relaxed); + if (handler != SIG_IGN && handler != SIG_DFL) { + atomic_store(&sigactions[signum], (uptr)handler, memory_order_relaxed); + handler = &SignalHandler; + } + + sighandler_t ret = signal(signum, handler); + + if (ret != SIG_ERR && ret == SignalHandler) + ret = (sighandler_t)old_cb; + + *ret_label = 0; + return ret; +} + SANITIZER_INTERFACE_ATTRIBUTE int __dfsw_sigaltstack(const stack_t *ss, stack_t *old_ss, dfsan_label ss_label, dfsan_label old_ss_label, dfsan_label *ret_label) { diff --git a/compiler-rt/lib/dfsan/done_abilist.txt b/compiler-rt/lib/dfsan/done_abilist.txt --- a/compiler-rt/lib/dfsan/done_abilist.txt +++ b/compiler-rt/lib/dfsan/done_abilist.txt @@ -252,6 +252,7 @@ fun:select=custom fun:sigemptyset=custom fun:sigaction=custom +fun:signal=custom fun:gettimeofday=custom # sprintf-like diff --git a/compiler-rt/test/dfsan/custom.cpp b/compiler-rt/test/dfsan/custom.cpp --- a/compiler-rt/test/dfsan/custom.cpp +++ b/compiler-rt/test/dfsan/custom.cpp @@ -842,6 +842,20 @@ assert(oldact.sa_handler == SignalHandler); } +void test_signal() { + // Set signal to be SignalHandler, save the previous one into + // old_signal_handler. + sighandler_t old_signal_handler = signal(SIGHUP, SignalHandler); + ASSERT_ZERO_LABEL(old_signal_handler); + + // Set SIG_IGN or SIG_DFL, and check the previous one is expected. + assert(SignalHandler == signal(SIGHUP, SIG_DFL)); + assert(SIG_DFL == signal(SIGHUP, SIG_IGN)); + + // Restore signal to old_signal_handler. + assert(SIG_IGN == signal(SIGHUP, old_signal_handler)); +} + void test_sigaltstack() { stack_t old_altstack = {}; dfsan_set_label(j_label, &old_altstack, sizeof(old_altstack)); @@ -1311,6 +1325,7 @@ test_sched_getaffinity(); test_select(); test_sigaction(); + test_signal(); test_sigaltstack(); test_sigemptyset(); test_snprintf();