From a8f3923f3711648a2d9fd68c8f746ca21ab4f564 Mon Sep 17 00:00:00 2001 From: Jan Vorlicek Date: Fri, 16 Jun 2017 13:23:34 +0200 Subject: [PATCH] Fix chained hardware exception handling on Unix (dotnet/coreclr#12316) There is an issue when hardware exception occurs while handling another hardware exception. In such case, the exception unwinding ends up in an infinite loop. It is caused by the kernel reusing the same location for signal handler context. The fix is to use the windows style context local variable in the common_signal_handler that contains the right context - it is the original signal context converted to windows style context. Commit migrated from https://github.com/dotnet/coreclr/commit/b594d588bc8a7778c30cf0445599ce97cc2edac9 --- src/coreclr/src/pal/src/exception/seh-unwind.cpp | 11 +++-------- src/coreclr/src/pal/src/exception/signal.cpp | 4 ++-- 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/src/coreclr/src/pal/src/exception/seh-unwind.cpp b/src/coreclr/src/pal/src/exception/seh-unwind.cpp index ba43c2e..360ea3e 100644 --- a/src/coreclr/src/pal/src/exception/seh-unwind.cpp +++ b/src/coreclr/src/pal/src/exception/seh-unwind.cpp @@ -261,18 +261,13 @@ BOOL PAL_VirtualUnwind(CONTEXT *context, KNONVOLATILE_CONTEXT_POINTERS *contextP #ifndef __APPLE__ // Check if the PC is the return address from the SEHProcessException in the common_signal_handler. - // If that's the case, extract its local variable containing the native_context_t of the hardware + // If that's the case, extract its local variable containing the windows style context of the hardware // exception and return that. This skips the hardware signal handler trampoline that the libunwind // cannot cross on some systems. if ((void*)curPc == g_SEHProcessExceptionReturnAddress) { - ULONG contextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_FLOATING_POINT | CONTEXT_EXCEPTION_ACTIVE; - - #if defined(_AMD64_) - contextFlags |= CONTEXT_XSTATE; - #endif - size_t nativeContext = *(size_t*)(CONTEXTGetFP(context) + g_common_signal_handler_context_locvar_offset); - CONTEXTFromNativeContext((const native_context_t *)nativeContext, context, contextFlags); + CONTEXT* nativeContext = *(CONTEXT**)(CONTEXTGetFP(context) + g_common_signal_handler_context_locvar_offset); + memcpy_s(context, sizeof(CONTEXT), nativeContext, sizeof(CONTEXT)); return TRUE; } diff --git a/src/coreclr/src/pal/src/exception/signal.cpp b/src/coreclr/src/pal/src/exception/signal.cpp index b82daca..6a046bd 100644 --- a/src/coreclr/src/pal/src/exception/signal.cpp +++ b/src/coreclr/src/pal/src/exception/signal.cpp @@ -119,7 +119,7 @@ struct sigaction g_previous_sigquit; struct sigaction g_previous_activation; #endif -// Offset of the local variable containing native context in the common_signal_handler function. +// Offset of the local variable containing pointer to windows style context in the common_signal_handler function. // This offset is relative to the frame pointer. int g_common_signal_handler_context_locvar_offset = 0; #endif // !HAVE_MACH_EXCEPTIONS @@ -766,7 +766,7 @@ static bool common_signal_handler(int code, siginfo_t *siginfo, void *sigcontext native_context_t *ucontext; ucontext = (native_context_t *)sigcontext; - g_common_signal_handler_context_locvar_offset = (int)((char*)&ucontext - (char*)__builtin_frame_address(0)); + g_common_signal_handler_context_locvar_offset = (int)((char*)&contextRecord - (char*)__builtin_frame_address(0)); AllocateExceptionRecords(&exceptionRecord, &contextRecord); -- 2.7.4