Index: lib/sanitizer_common/sanitizer_posix_libcdep.cc =================================================================== --- lib/sanitizer_common/sanitizer_posix_libcdep.cc +++ lib/sanitizer_common/sanitizer_posix_libcdep.cc @@ -191,6 +191,19 @@ if (!IsHandledDeadlySignal(signum)) return; struct sigaction sigact; + if (common_flags()->allow_user_signal_handler) { + internal_memset(&sigact, 0, sizeof(sigact)); + CHECK_EQ(0, internal_sigaction(signum, nullptr, &sigact)); + if (sigact.sa_flags & SA_SIGINFO) { + if (sigact.sa_sigaction) return; + } else { + if (sigact.sa_handler != SIG_DFL && sigact.sa_handler != SIG_IGN && + sigact.sa_handler != SIG_ERR) { + return; + } + } + } + internal_memset(&sigact, 0, sizeof(sigact)); sigact.sa_sigaction = (sa_sigaction_t)handler; // Do not block the signal from being received in that signal's handler. Index: test/asan/TestCases/Linux/preinstalled_signal.cc =================================================================== --- /dev/null +++ test/asan/TestCases/Linux/preinstalled_signal.cc @@ -0,0 +1,76 @@ +// RUN: %clangxx -std=c++11 %s -ldl -o %t + +// RUN: %env_asan_opts=verify_asan_link_order=false:allow_user_signal_handler=true not %run %t %shared_libasan 0 0 2>&1 | FileCheck %s +// RUN: %env_asan_opts=verify_asan_link_order=false:allow_user_signal_handler=true not %run %t %shared_libasan 1 1 2>&1 | FileCheck --check-prefix=CHECK-HANDLER %s +// RUN: %env_asan_opts=verify_asan_link_order=false:allow_user_signal_handler=true not %run %t %shared_libasan 2 1 2>&1 | FileCheck --check-prefix=CHECK-ACTION %s + +// RUN: %env_asan_opts=verify_asan_link_order=false:allow_user_signal_handler=false not %run %t %shared_libasan 0 0 2>&1 | FileCheck %s +// RUN: %env_asan_opts=verify_asan_link_order=false:allow_user_signal_handler=false not %run %t %shared_libasan 1 0 2>&1 | FileCheck %s +// RUN: %env_asan_opts=verify_asan_link_order=false:allow_user_signal_handler=false not %run %t %shared_libasan 2 0 2>&1 | FileCheck %s + +// REQUIRES: asan-dynamic-runtime + +#include +#include +#include +#include +#include + +const char *handler = NULL; + +void SigHandler(int signum) { handler = "TestSigHandler"; } + +void SigAction(int, siginfo_t *, void *) { handler = "TestSigAction"; } + +int main(int argc, char *argv[]) { + struct sigaction sigact = {}; + sigaction(SIGSEGV, NULL, &sigact); + assert(sigact.sa_handler == SIG_DFL || sigact.sa_handler == SIG_IGN); + + const char *asan_rt = argv[1]; + int handler_type = atoi(argv[2]); + bool keep_user_handler = atoi(argv[3]); + + switch (handler_type) { + case 1: + sigact = {}; + sigact.sa_handler = &SigHandler; + sigaction(SIGSEGV, &sigact, NULL); + break; + case 2: + sigact = {}; + sigact.sa_flags = SA_SIGINFO | SA_NODEFER; + sigact.sa_sigaction = &SigAction; + sigaction(SIGSEGV, &sigact, NULL); + break; + }; + + void *asan = dlopen(asan_rt, RTLD_NOW); + assert(asan); + + struct sigaction sigact_asan = {}; + sigaction(SIGSEGV, NULL, &sigact_asan); + + assert(sigact_asan.sa_handler != SIG_DFL); + assert(sigact_asan.sa_handler != SIG_IGN); + + assert(keep_user_handler == (sigact_asan.sa_handler == sigact.sa_handler)); + assert(keep_user_handler == + (sigact_asan.sa_sigaction == sigact.sa_sigaction)); + + raise(SIGSEGV); + + printf("%s\n", handler); + + dlclose(asan); + return !!handler; +} + +// CHECK-NOT: TestSig +// CHECK: ASAN:DEADLYSIGNAL + +// CHECK-HANDLER-NOT: ASAN:DEADLYSIGNAL +// CHECK-HANDLER: TestSigHandler + +// CHECK-ACTION-NOT: ASAN:DEADLYSIGNAL +// CHECK-ACTION: TestSigAction