diff options
author | Vitaly Buka <vitalybuka@google.com> | 2017-05-26 21:51:26 +0000 |
---|---|---|
committer | Vitaly Buka <vitalybuka@google.com> | 2017-05-26 21:51:26 +0000 |
commit | f9198fc26c8e502bffa758b451b8ded20bb9a7f4 (patch) | |
tree | e2257c7f1b579790554c7ec7be3dbaeaa4449faa /test/asan/TestCases/Linux | |
parent | 0338f3e77f7589bc43a1a9b38e7324334da1939c (diff) |
[compiler-rt] Don't reset non-default user handler if allow_user_segv_handler is true.
Reviewers: eugenis, kcc
Subscribers: kubamracek, llvm-commits
Differential Revision: https://reviews.llvm.org/D32457
git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@304039 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'test/asan/TestCases/Linux')
-rw-r--r-- | test/asan/TestCases/Linux/preinstalled_signal.cc | 105 |
1 files changed, 105 insertions, 0 deletions
diff --git a/test/asan/TestCases/Linux/preinstalled_signal.cc b/test/asan/TestCases/Linux/preinstalled_signal.cc new file mode 100644 index 000000000..40dadf43d --- /dev/null +++ b/test/asan/TestCases/Linux/preinstalled_signal.cc @@ -0,0 +1,105 @@ +// clang-format off +// RUN: %clangxx -std=c++11 %s -o %t +// RUN: env LD_PRELOAD=%shared_libasan %env_asan_opts=handle_segv=1 not %run %t 2>&1 | FileCheck %s +// RUN: env LD_PRELOAD=%shared_libasan %env_asan_opts=handle_segv=2 not %run %t 2>&1 | FileCheck %s + +// RUN: %clangxx -std=c++11 -DTEST_INSTALL_SIG_HANDLER %s -o %t +// RUN: env LD_PRELOAD=%shared_libasan %env_asan_opts=handle_segv=1 not %run %t 2>&1 | FileCheck --check-prefix=CHECK-HANDLER %s +// RUN: env LD_PRELOAD=%shared_libasan %env_asan_opts=handle_segv=2 not %run %t 2>&1 | FileCheck %s + +// RUN: %clangxx -std=c++11 -DTEST_INSTALL_SIG_ACTION %s -o %t +// RUN: env LD_PRELOAD=%shared_libasan %env_asan_opts=handle_segv=1 not %run %t 2>&1 | FileCheck --check-prefix=CHECK-ACTION %s +// RUN: env LD_PRELOAD=%shared_libasan %env_asan_opts=handle_segv=2 not %run %t 2>&1 | FileCheck %s + +// REQUIRES: asan-dynamic-runtime + +// This way of setting LD_PRELOAD does not work with Android test runner. +// REQUIRES: not-android +// clang-format on + +#include <assert.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/syscall.h> +#include <unistd.h> + +const char *handler = nullptr; +void SigHandler(int signum) { handler = "TestSigHandler"; } +void SigAction(int, siginfo_t *, void *) { handler = "TestSigAction"; } + +struct KernelSigaction { + __sighandler_t handler; + unsigned long flags; + void (*restorer)(); + char unused[1024]; +}; + +#if defined(__x86_64__) +extern "C" void restorer(); +asm("restorer:mov $15,%rax\nsyscall"); +#endif + +int InternalSigaction(int sig, KernelSigaction *act, KernelSigaction *oact) { + if (act) { +#if defined(__x86_64__) + act->flags |= 0x04000000; + act->restorer = &restorer; +#endif + } + return syscall(__NR_rt_sigaction, sig, act, oact, NSIG / 8); +} + +struct KernelSigaction sigact = {}; + +static void Init() { + int res = InternalSigaction(SIGSEGV, nullptr, &sigact); + assert(res >= 0); + assert(sigact.handler == SIG_DFL || sigact.handler == SIG_IGN); +#if defined(TEST_INSTALL_SIG_HANDLER) + sigact = {}; + sigact.handler = &SigHandler; + res = InternalSigaction(SIGSEGV, &sigact, nullptr); + assert(res >= 0); +#elif defined(TEST_INSTALL_SIG_ACTION) + sigact = {}; + sigact.flags = SA_SIGINFO | SA_NODEFER; + sigact.handler = (__sighandler_t)&SigAction; + res = InternalSigaction(SIGSEGV, &sigact, nullptr); + assert(res >= 0); +#endif +} + +__attribute__((section(".preinit_array"), used)) +void (*__local_test_preinit)(void) = Init; + +bool ShouldAsanInstallHandlers() { +#if defined(TEST_INSTALL_SIG_HANDLER) || defined(TEST_INSTALL_SIG_ACTION) + return !strcmp(getenv("ASAN_OPTIONS"), "handle_segv=2"); +#endif + return true; +} + +int main(int argc, char *argv[]) { + KernelSigaction sigact_asan = {}; + InternalSigaction(SIGSEGV, nullptr, &sigact_asan); + + assert(sigact_asan.handler != SIG_DFL); + assert(sigact_asan.handler != SIG_IGN); + assert(ShouldAsanInstallHandlers() == + (sigact_asan.handler != sigact.handler)); + + raise(SIGSEGV); + printf("%s\n", handler); + return 1; +} + +// CHECK-NOT: TestSig +// CHECK: ASAN:DEADLYSIGNAL + +// CHECK-HANDLER-NOT: ASAN:DEADLYSIGNAL +// CHECK-HANDLER: TestSigHandler + +// CHECK-ACTION-NOT: ASAN:DEADLYSIGNAL +// CHECK-ACTION: TestSigAction |