diff options
| -rw-r--r-- | compiler-rt/lib/asan/asan_internal.h | 3 | ||||
| -rw-r--r-- | compiler-rt/lib/asan/asan_posix.cc | 36 | ||||
| -rw-r--r-- | compiler-rt/lib/asan/asan_rtl.cc | 5 | ||||
| -rw-r--r-- | compiler-rt/lib/asan/asan_thread.cc | 2 | ||||
| -rw-r--r-- | compiler-rt/lib/asan/asan_win.cc | 8 | 
5 files changed, 53 insertions, 1 deletions
diff --git a/compiler-rt/lib/asan/asan_internal.h b/compiler-rt/lib/asan/asan_internal.h index 6f03d678be1..39d3adf07a6 100644 --- a/compiler-rt/lib/asan/asan_internal.h +++ b/compiler-rt/lib/asan/asan_internal.h @@ -181,6 +181,8 @@ size_t AsanWrite(int fd, const void *buf, size_t count);  int AsanClose(int fd);  bool AsanInterceptsSignal(int signum); +void SetAlternateSignalStack(); +void UnsetAlternateSignalStack();  void InstallSignalHandlers();  int GetPid();  uintptr_t GetThreadSelf(); @@ -249,6 +251,7 @@ extern int    FLAG_exitcode;  extern bool   FLAG_allow_user_poisoning;  extern int    FLAG_sleep_before_dying;  extern bool   FLAG_handle_segv; +extern bool   FLAG_use_sigaltstack;  extern int asan_inited;  // Used to avoid infinite recursion in __asan_init(). diff --git a/compiler-rt/lib/asan/asan_posix.cc b/compiler-rt/lib/asan/asan_posix.cc index 15bdd932e10..0ab09e615dc 100644 --- a/compiler-rt/lib/asan/asan_posix.cc +++ b/compiler-rt/lib/asan/asan_posix.cc @@ -34,6 +34,8 @@  // since most of the stuff here is inlinable.  #include <algorithm> +static const size_t kAltStackSize = SIGSTKSZ * 4;  // SIGSTKSZ is not enough. +  namespace __asan {  static void MaybeInstallSigaction(int signum, @@ -44,6 +46,7 @@ static void MaybeInstallSigaction(int signum,    REAL(memset)(&sigact, 0, sizeof(sigact));    sigact.sa_sigaction = handler;    sigact.sa_flags = SA_SIGINFO; +  if (FLAG_use_sigaltstack) sigact.sa_flags |= SA_ONSTACK;    CHECK(0 == REAL(sigaction)(signum, &sigact, 0));  } @@ -63,7 +66,40 @@ static void     ASAN_OnSIGSEGV(int, siginfo_t *siginfo, void *context) {    ShowStatsAndAbort();  } +void SetAlternateSignalStack() { +  stack_t altstack, oldstack; +  CHECK(0 == sigaltstack(NULL, &oldstack)); +  // If the alternate stack is already in place, do nothing. +  if ((oldstack.ss_flags & SS_DISABLE) == 0) return; +  // TODO(glider): the mapped stack should have the MAP_STACK flag in the +  // future. It is not required by man 2 sigaltstack now (they're using +  // malloc()). +  void* base = AsanMmapSomewhereOrDie(kAltStackSize, __FUNCTION__); +  altstack.ss_sp = base; +  altstack.ss_flags = 0; +  altstack.ss_size = kAltStackSize; +  CHECK(0 == sigaltstack(&altstack, NULL)); +  if (FLAG_v > 0) { +    Report("Alternative stack for T%d set: [%p,%p)\n", +           asanThreadRegistry().GetCurrentTidOrMinusOne(), +           altstack.ss_sp, (char*)altstack.ss_sp + altstack.ss_size); +  } +} + +void UnsetAlternateSignalStack() { +  stack_t altstack, oldstack; +  altstack.ss_sp = NULL; +  altstack.ss_flags = SS_DISABLE; +  altstack.ss_size = 0; +  CHECK(0 == sigaltstack(&altstack, &oldstack)); +  AsanUnmapOrDie(oldstack.ss_sp, oldstack.ss_size); +} +  void InstallSignalHandlers() { +  // Set the alternate signal stack for the main thread. +  // This will cause SetAlternateSignalStack to be called twice, but the stack +  // will be actually set only once. +  if (FLAG_use_sigaltstack) SetAlternateSignalStack();    MaybeInstallSigaction(SIGSEGV, ASAN_OnSIGSEGV);    MaybeInstallSigaction(SIGBUS, ASAN_OnSIGSEGV);  } diff --git a/compiler-rt/lib/asan/asan_rtl.cc b/compiler-rt/lib/asan/asan_rtl.cc index 3587d45145d..8f69cca2869 100644 --- a/compiler-rt/lib/asan/asan_rtl.cc +++ b/compiler-rt/lib/asan/asan_rtl.cc @@ -39,6 +39,7 @@ int    FLAG_report_globals;  size_t FLAG_malloc_context_size = kMallocContextSize;  uintptr_t FLAG_large_malloc;  bool   FLAG_handle_segv; +bool   FLAG_use_sigaltstack;  bool   FLAG_replace_str;  bool   FLAG_replace_intrin;  bool   FLAG_replace_cfallocator;  // Used on Mac only. @@ -442,6 +443,7 @@ void __asan_init() {    FLAG_poison_shadow = IntFlagValue(options, "poison_shadow=", 1);    FLAG_report_globals = IntFlagValue(options, "report_globals=", 1);    FLAG_handle_segv = IntFlagValue(options, "handle_segv=", ASAN_NEEDS_SEGV); +  FLAG_use_sigaltstack = IntFlagValue(options, "use_sigaltstack=", 0);    FLAG_symbolize = IntFlagValue(options, "symbolize=", 1);    FLAG_demangle = IntFlagValue(options, "demangle=", 1);    FLAG_debug = IntFlagValue(options, "debug=", 0); @@ -470,7 +472,6 @@ void __asan_init() {    InitializeAsanInterceptors();    ReplaceSystemMalloc(); -  InstallSignalHandlers();    if (FLAG_v) {      Printf("|| `[%p, %p]` || HighMem    ||\n", kHighMemBeg, kHighMemEnd); @@ -517,6 +518,8 @@ void __asan_init() {      AsanDie();    } +  InstallSignalHandlers(); +    // On Linux AsanThread::ThreadStart() calls malloc() that's why asan_inited    // should be set to 1 prior to initializing the threads.    asan_inited = 1; diff --git a/compiler-rt/lib/asan/asan_thread.cc b/compiler-rt/lib/asan/asan_thread.cc index b6d0965c755..315db7ef98f 100644 --- a/compiler-rt/lib/asan/asan_thread.cc +++ b/compiler-rt/lib/asan/asan_thread.cc @@ -82,6 +82,7 @@ void AsanThread::Init() {  thread_return_t AsanThread::ThreadStart() {    Init(); +  if (FLAG_use_sigaltstack) SetAlternateSignalStack();    if (!start_routine_) {      // start_routine_ == NULL if we're on the main thread or on one of the @@ -93,6 +94,7 @@ thread_return_t AsanThread::ThreadStart() {    thread_return_t res = start_routine_(arg_);    malloc_storage().CommitBack(); +  if (FLAG_use_sigaltstack) UnsetAlternateSignalStack();    this->Destroy(); diff --git a/compiler-rt/lib/asan/asan_win.cc b/compiler-rt/lib/asan/asan_win.cc index b3a770b8276..94f4d04a18a 100644 --- a/compiler-rt/lib/asan/asan_win.cc +++ b/compiler-rt/lib/asan/asan_win.cc @@ -262,6 +262,14 @@ uintptr_t GetThreadSelf() {    return GetCurrentThreadId();  } +void SetAlternateSignalStack() { +  // FIXME: Decide what to do on Windows. +} + +void UnsetAlternateSignalStack() { +  // FIXME: Decide what to do on Windows. +} +  void InstallSignalHandlers() {    // FIXME: Decide what to do on Windows.  }  | 

