[compiler-rt] r304039 - [compiler-rt] Don't reset non-default user handler if allow_user_segv_handler is true.

Vitaly Buka via llvm-commits llvm-commits at lists.llvm.org
Fri May 26 14:51:27 PDT 2017


Author: vitalybuka
Date: Fri May 26 16:51:26 2017
New Revision: 304039

URL: http://llvm.org/viewvc/llvm-project?rev=304039&view=rev
Log:
[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

Added:
    compiler-rt/trunk/test/asan/TestCases/Linux/preinstalled_signal.cc
Modified:
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_posix_libcdep.cc

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_posix_libcdep.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_posix_libcdep.cc?rev=304039&r1=304038&r2=304039&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_posix_libcdep.cc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_posix_libcdep.cc Fri May 26 16:51:26 2017
@@ -189,7 +189,25 @@ void UnsetAlternateSignalStack() {
 
 static void MaybeInstallSigaction(int signum,
                                   SignalHandlerType handler) {
-  if (GetHandleSignalMode(signum) == kHandleSignalNo) return;
+  switch (GetHandleSignalMode(signum)) {
+    case kHandleSignalNo:
+      return;
+    case kHandleSignalYes: {
+      struct sigaction sigact;
+      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;
+      }
+      break;
+    }
+    case kHandleSignalExclusive:
+      break;
+  }
 
   struct sigaction sigact;
   internal_memset(&sigact, 0, sizeof(sigact));

Added: compiler-rt/trunk/test/asan/TestCases/Linux/preinstalled_signal.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/asan/TestCases/Linux/preinstalled_signal.cc?rev=304039&view=auto
==============================================================================
--- compiler-rt/trunk/test/asan/TestCases/Linux/preinstalled_signal.cc (added)
+++ compiler-rt/trunk/test/asan/TestCases/Linux/preinstalled_signal.cc Fri May 26 16:51:26 2017
@@ -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




More information about the llvm-commits mailing list