Skip to content

Commit

Permalink
Fix stack overflow handling with SuperPMI (#106495)
Browse files Browse the repository at this point in the history
* Fix stack overflow handling with SuperPMI

When SuperPMI shared library is loaded last, its SIGSEGV handler
is the first one that's executed. But since there is no coreclr runtime handler
installed for it, it returns from the SwitchStackAndExecuteHandler in case
of SIGSEGV. The remaining code in the SIGSEGV handler was not expecting that and
thought that there was no stack overflow and attempted to run the hardware exception
handler on the original stack of the thread, which obviously crashed since the original
stack overflowed.
The fix is to make sure that we only call the previously registered signal handler in
this case.

Close #84911

* PR feedback
  • Loading branch information
janvorli authored Aug 16, 2024
1 parent fc7a8e6 commit 9230f2b
Showing 1 changed file with 22 additions and 17 deletions.
39 changes: 22 additions & 17 deletions src/coreclr/pal/src/exception/signal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -641,34 +641,39 @@ static void sigsegv_handler(int code, siginfo_t *siginfo, void *context)
{
PROCAbort(SIGSEGV, siginfo);
}

// The current executable (shared library) doesn't have hardware exception handler installed or opted to not to
// handle it. So this handler will invoke the previously installed handler at the end of this function.
}
else
{
(void)!write(STDERR_FILENO, StackOverflowMessage, sizeof(StackOverflowMessage) - 1);
PROCAbort(SIGSEGV, siginfo);
}
}

// Now that we know the SIGSEGV didn't happen due to a stack overflow, execute the common
// hardware signal handler on the original stack.

if (GetCurrentPalThread() && IsRunningOnAlternateStack(context))
else
{
if (SwitchStackAndExecuteHandler(code, siginfo, context, 0 /* sp */)) // sp == 0 indicates execution on the original stack
// Now that we know the SIGSEGV didn't happen due to a stack overflow, execute the common
// hardware signal handler on the original stack.

if (GetCurrentPalThread() && IsRunningOnAlternateStack(context))
{
return;
if (SwitchStackAndExecuteHandler(code, siginfo, context, 0 /* sp */)) // sp == 0 indicates execution on the original stack
{
return;
}
}
}
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.
if (common_signal_handler(code, siginfo, context, 2, (size_t)0, (size_t)siginfo->si_addr))
else
{
return;
// 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.
if (common_signal_handler(code, siginfo, context, 2, (size_t)0, (size_t)siginfo->si_addr))
{
return;
}
}
}
}
Expand Down

0 comments on commit 9230f2b

Please sign in to comment.