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,30 @@ 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); + uptr cb = (uptr)handler; + if (cb != (uptr)SIG_IGN && cb != (uptr)SIG_DFL) { + atomic_store(&sigactions[signum], cb, memory_order_relaxed); + cb = (uptr)&SignalHandler; + } + + sighandler_t ret = signal(signum, (sighandler_t)cb); + + if (ret != SIG_ERR) + 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,19 @@ 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 signal and check the previous one is SignalHandler. + assert(SignalHandler == signal(SIGHUP, SIG_DFL)); + + // Restore signal to old_signal_handler. + assert(SignalHandler == signal(SIGHUP, old_signal_handler)); +} + void test_sigaltstack() { stack_t old_altstack = {}; dfsan_set_label(j_label, &old_altstack, sizeof(old_altstack)); @@ -1311,6 +1324,7 @@ test_sched_getaffinity(); test_select(); test_sigaction(); + test_signal(); test_sigaltstack(); test_sigemptyset(); test_snprintf();