diff options
author | Jan Vorlicek <janvorli@microsoft.com> | 2019-06-17 23:13:33 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-06-17 23:13:33 +0200 |
commit | 4f6cc4aff1356802f04a7d6bb7a40c1642f7e96e (patch) | |
tree | 7eccb6095896c688b31261f82dc8f11fea98c88c /src/pal | |
parent | 57a6eb69b3d6005962ad2ae48db18dff268aff56 (diff) | |
download | coreclr-4f6cc4aff1356802f04a7d6bb7a40c1642f7e96e.tar.gz coreclr-4f6cc4aff1356802f04a7d6bb7a40c1642f7e96e.tar.bz2 coreclr-4f6cc4aff1356802f04a7d6bb7a40c1642f7e96e.zip |
Enable running SIGSEGV handler on non-alternate stack (#25196)
When a third party library that someone loads into a coreclr process registers
its own SIGSEGV handler and then chain-calls coreclr SIGSEGV handler on a
non-alternate stack, coreclr would currently crash.
This fix enables it to execute the SIGSEGV handler on the non-alternate stack
(original stack of the interrupted thread) in such case.
The disadvantage is that stack overflow would lead to silent crash in such a
case, but we cannot do anything about it.
Diffstat (limited to 'src/pal')
-rw-r--r-- | src/pal/src/exception/signal.cpp | 30 |
1 files changed, 27 insertions, 3 deletions
diff --git a/src/pal/src/exception/signal.cpp b/src/pal/src/exception/signal.cpp index df5a5f22a4..fbd94a886b 100644 --- a/src/pal/src/exception/signal.cpp +++ b/src/pal/src/exception/signal.cpp @@ -389,6 +389,28 @@ extern "C" void signal_handler_worker(int code, siginfo_t *siginfo, void *contex /*++ Function : + IsRunningOnAlternateStack + + Detects if the current signal handlers is running on an alternate stack + +Parameters : + The context of the signal + +Return : + true if we are running on an alternate stack + +--*/ +bool IsRunningOnAlternateStack(void *context) +{ + stack_t *signalStack = &((native_context_t *)context)->uc_stack; + // Check if the signalStack local variable address is within the alternate stack range. If it is not, + // then either the alternate stack was not installed at all or the current method is not running on it. + void* alternateStackEnd = (char *)signalStack->ss_sp + signalStack->ss_size; + return ((signalStack->ss_flags & SS_DISABLE) == 0) && (signalStack->ss_sp <= &signalStack) && (&signalStack < alternateStackEnd); +} + +/*++ +Function : sigsegv_handler handle SIGSEGV signal (EXCEPTION_ACCESS_VIOLATION, others) @@ -417,10 +439,10 @@ static void sigsegv_handler(int code, siginfo_t *siginfo, void *context) // Now that we know the SIGSEGV didn't happen due to a stack overflow, execute the common // hardware signal handler on the original stack. - // Establish a return point in case the common_signal_handler returns - - if (GetCurrentPalThread()) + if (GetCurrentPalThread() && IsRunningOnAlternateStack(context)) { + // Establish a return point in case the common_signal_handler returns + volatile bool contextInitialization = true; void *ptr = alloca(sizeof(SignalHandlerWorkerReturnPoint) + alignof(SignalHandlerWorkerReturnPoint) - 1); @@ -443,6 +465,8 @@ static void sigsegv_handler(int code, siginfo_t *siginfo, void *context) } else { + // The code flow gets here when the signal handler is not running on an alternate stack or when it wasn't created + // by coreclr. In both cases, we execute the common_signal_handler directly. // If thread isn't created by coreclr and has alternate signal stack GetCurrentPalThread() will return NULL too. // But since in this case we don't handle hardware exceptions (IsSafeToHandleHardwareException returns false) // we can call common_signal_handler on the alternate stack. |