aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexey Samsonov <samsonov@google.com>2013-04-25 10:52:15 +0000
committerAlexey Samsonov <samsonov@google.com>2013-04-25 10:52:15 +0000
commit332bf3340435a85d39d6abefbf4d6a145e17da1c (patch)
treebd7b6262dd194622dc3497376b8c832ef073cd90
parent45269092b22468fd1f9c74de04f8560c05d5b862 (diff)
downloadcompiler-rt-332bf3340435a85d39d6abefbf4d6a145e17da1c.tar.gz
[ASan] Add allow_user_segv_handler to let users override SEGV handler installed by ASan
git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@180255 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/asan/asan_flags.h2
-rw-r--r--lib/asan/asan_interceptors.cc4
-rw-r--r--lib/asan/asan_rtl.cc2
-rw-r--r--lib/asan/lit_tests/allow_user_segv.cc42
4 files changed, 48 insertions, 2 deletions
diff --git a/lib/asan/asan_flags.h b/lib/asan/asan_flags.h
index 98909b3d7..8debcd299 100644
--- a/lib/asan/asan_flags.h
+++ b/lib/asan/asan_flags.h
@@ -71,6 +71,8 @@ struct Flags {
int sleep_before_dying;
// If set, registers ASan custom segv handler.
bool handle_segv;
+ // If set, allows user register segv handler even if ASan registers one.
+ bool allow_user_segv_handler;
// If set, uses alternate stack for signal handling.
bool use_sigaltstack;
// Allow the users to work around the bug in Nvidia drivers prior to 295.*.
diff --git a/lib/asan/asan_interceptors.cc b/lib/asan/asan_interceptors.cc
index 1a6d95ec5..0c467b36c 100644
--- a/lib/asan/asan_interceptors.cc
+++ b/lib/asan/asan_interceptors.cc
@@ -154,7 +154,7 @@ INTERCEPTOR(int, pthread_create, void *thread,
#if ASAN_INTERCEPT_SIGNAL_AND_SIGACTION
INTERCEPTOR(void*, signal, int signum, void *handler) {
- if (!AsanInterceptsSignal(signum)) {
+ if (!AsanInterceptsSignal(signum) || flags()->allow_user_segv_handler) {
return REAL(signal)(signum, handler);
}
return 0;
@@ -162,7 +162,7 @@ INTERCEPTOR(void*, signal, int signum, void *handler) {
INTERCEPTOR(int, sigaction, int signum, const struct sigaction *act,
struct sigaction *oldact) {
- if (!AsanInterceptsSignal(signum)) {
+ if (!AsanInterceptsSignal(signum) || flags()->allow_user_segv_handler) {
return REAL(sigaction)(signum, act, oldact);
}
return 0;
diff --git a/lib/asan/asan_rtl.cc b/lib/asan/asan_rtl.cc
index d6f7bc6bd..03158f31b 100644
--- a/lib/asan/asan_rtl.cc
+++ b/lib/asan/asan_rtl.cc
@@ -107,6 +107,7 @@ static void ParseFlagsFromString(Flags *f, const char *str) {
ParseFlag(str, &f->allow_user_poisoning, "allow_user_poisoning");
ParseFlag(str, &f->sleep_before_dying, "sleep_before_dying");
ParseFlag(str, &f->handle_segv, "handle_segv");
+ ParseFlag(str, &f->allow_user_segv_handler, "allow_user_segv_handler");
ParseFlag(str, &f->use_sigaltstack, "use_sigaltstack");
ParseFlag(str, &f->check_malloc_usable_size, "check_malloc_usable_size");
ParseFlag(str, &f->unmap_shadow_on_exit, "unmap_shadow_on_exit");
@@ -151,6 +152,7 @@ void InitializeFlags(Flags *f, const char *env) {
f->allow_user_poisoning = true;
f->sleep_before_dying = 0;
f->handle_segv = ASAN_NEEDS_SEGV;
+ f->allow_user_segv_handler = false;
f->use_sigaltstack = false;
f->check_malloc_usable_size = true;
f->unmap_shadow_on_exit = false;
diff --git a/lib/asan/lit_tests/allow_user_segv.cc b/lib/asan/lit_tests/allow_user_segv.cc
new file mode 100644
index 000000000..7d5ab9336
--- /dev/null
+++ b/lib/asan/lit_tests/allow_user_segv.cc
@@ -0,0 +1,42 @@
+// Regression test for
+// https://code.google.com/p/address-sanitizer/issues/detail?id=180
+
+// RUN: %clangxx_asan -m64 -O0 %s -o %t && ASAN_OPTIONS=allow_user_segv_handler=true %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -m64 -O2 %s -o %t && ASAN_OPTIONS=allow_user_segv_handler=true %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -m32 -O0 %s -o %t && ASAN_OPTIONS=allow_user_segv_handler=true %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan -m32 -O2 %s -o %t && ASAN_OPTIONS=allow_user_segv_handler=true %t 2>&1 | FileCheck %s
+
+#include <signal.h>
+#include <stdio.h>
+
+struct sigaction user_sigaction;
+struct sigaction original_sigaction;
+
+void User_OnSIGSEGV(int signum, siginfo_t *siginfo, void *context) {
+ fprintf(stderr, "User sigaction called\n");
+ if (original_sigaction.sa_flags | SA_SIGINFO)
+ original_sigaction.sa_sigaction(signum, siginfo, context);
+ else
+ original_sigaction.sa_handler(signum);
+}
+
+int DoSEGV() {
+ volatile int *x = 0;
+ return *x;
+}
+
+int main() {
+ user_sigaction.sa_sigaction = User_OnSIGSEGV;
+ user_sigaction.sa_flags = SA_SIGINFO;
+ if (sigaction(SIGSEGV, &user_sigaction, &original_sigaction)) {
+ perror("sigaction");
+ return 1;
+ }
+ fprintf(stderr, "User sigaction installed\n");
+ return DoSEGV();
+}
+
+// CHECK: User sigaction installed
+// CHECK-NEXT: User sigaction called
+// CHECK-NEXT: ASAN:SIGSEGV
+// CHECK: AddressSanitizer: SEGV on unknown address