diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/asan/asan_flags.h | 2 | ||||
-rw-r--r-- | lib/asan/asan_interceptors.cc | 4 | ||||
-rw-r--r-- | lib/asan/asan_rtl.cc | 2 | ||||
-rw-r--r-- | lib/asan/lit_tests/allow_user_segv.cc | 42 |
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 |