summaryrefslogtreecommitdiff
path: root/src/pal/src/exception
diff options
context:
space:
mode:
authormlabiuk <35769704+mlabiuk@users.noreply.github.com>2018-02-20 23:35:26 +0300
committerJan Vorlicek <janvorli@microsoft.com>2018-02-20 21:35:26 +0100
commitd9753f42e8c77688f2e560febf378b2c190d8b02 (patch)
tree64fb8d1b9aaaecec9793080fd0f0bda4f7daab57 /src/pal/src/exception
parent007e08ec2ae2c86c11f90218224be2e37adaa572 (diff)
downloadcoreclr-d9753f42e8c77688f2e560febf378b2c190d8b02.tar.gz
coreclr-d9753f42e8c77688f2e560febf378b2c190d8b02.tar.bz2
coreclr-d9753f42e8c77688f2e560febf378b2c190d8b02.zip
Prevent memory allocation in signal handler (#16384)
* Do not allocate exception for signal from non managed code If the signal occurs in not managed code we cannot use heap. We should call signal-safe functions only from signal handler. Create exception object on stack for checking source of signal. If signal is from managed code we can use memory allocation to create persistent exception on heap as copy of volatile exception on stack. If signal from unmanaged code we do nothing and call base signal handler. fix https://github.com/dotnet/coreclr/issues/16338
Diffstat (limited to 'src/pal/src/exception')
-rw-r--r--src/pal/src/exception/seh.cpp34
-rw-r--r--src/pal/src/exception/signal.cpp30
2 files changed, 48 insertions, 16 deletions
diff --git a/src/pal/src/exception/seh.cpp b/src/pal/src/exception/seh.cpp
index 73d8ce505b..b05707076b 100644
--- a/src/pal/src/exception/seh.cpp
+++ b/src/pal/src/exception/seh.cpp
@@ -204,6 +204,38 @@ void ThrowExceptionHelper(PAL_SEHException* ex)
/*++
Function:
+ EnsureExceptionRecordsOnHeap
+
+ Helper function to move records from stack to heap.
+
+Parameters:
+ PAL_SEHException* exception
+--*/
+static void EnsureExceptionRecordsOnHeap(PAL_SEHException* exception)
+{
+ if( !exception->RecordsOnStack ||
+ exception->ExceptionPointers.ExceptionRecord == NULL )
+ {
+ return;
+ }
+
+ CONTEXT* contextRecord = exception->ExceptionPointers.ContextRecord;
+ EXCEPTION_RECORD* exceptionRecord = exception->ExceptionPointers.ExceptionRecord;
+
+ CONTEXT* contextRecordCopy;
+ EXCEPTION_RECORD* exceptionRecordCopy;
+ AllocateExceptionRecords(&exceptionRecordCopy, &contextRecordCopy);
+
+ *exceptionRecordCopy = *exceptionRecord;
+ *contextRecordCopy = *contextRecord;
+
+ exception->ExceptionPointers.ExceptionRecord = exceptionRecordCopy;
+ exception->ExceptionPointers.ContextRecord = contextRecordCopy;
+ exception->RecordsOnStack = false;
+}
+
+/*++
+Function:
SEHProcessException
Send the PAL exception to any handler registered.
@@ -250,6 +282,7 @@ SEHProcessException(PAL_SEHException* exception)
}
}
+ EnsureExceptionRecordsOnHeap(exception);
if (g_hardwareExceptionHandler(exception))
{
// The exception happened in managed code and the execution should continue.
@@ -262,6 +295,7 @@ SEHProcessException(PAL_SEHException* exception)
if (CatchHardwareExceptionHolder::IsEnabled())
{
+ EnsureExceptionRecordsOnHeap(exception);
PAL_ThrowExceptionFromContext(exception->GetContextRecord(), exception);
}
}
diff --git a/src/pal/src/exception/signal.cpp b/src/pal/src/exception/signal.cpp
index 96dca50706..6748d54f0f 100644
--- a/src/pal/src/exception/signal.cpp
+++ b/src/pal/src/exception/signal.cpp
@@ -845,32 +845,30 @@ static bool common_signal_handler(int code, siginfo_t *siginfo, void *sigcontext
{
sigset_t signal_set;
CONTEXT signalContextRecord;
- CONTEXT *contextRecord;
- EXCEPTION_RECORD *exceptionRecord;
+ CONTEXT contextRecord;
+ EXCEPTION_RECORD exceptionRecord;
native_context_t *ucontext;
ucontext = (native_context_t *)sigcontext;
g_common_signal_handler_context_locvar_offset = (int)((char*)&signalContextRecord - (char*)__builtin_frame_address(0));
- AllocateExceptionRecords(&exceptionRecord, &contextRecord);
-
- exceptionRecord->ExceptionCode = CONTEXTGetExceptionCodeForSignal(siginfo, ucontext);
- exceptionRecord->ExceptionFlags = EXCEPTION_IS_SIGNAL;
- exceptionRecord->ExceptionRecord = NULL;
- exceptionRecord->ExceptionAddress = GetNativeContextPC(ucontext);
- exceptionRecord->NumberParameters = numParams;
+ exceptionRecord.ExceptionCode = CONTEXTGetExceptionCodeForSignal(siginfo, ucontext);
+ exceptionRecord.ExceptionFlags = EXCEPTION_IS_SIGNAL;
+ exceptionRecord.ExceptionRecord = NULL;
+ exceptionRecord.ExceptionAddress = GetNativeContextPC(ucontext);
+ exceptionRecord.NumberParameters = numParams;
va_list params;
va_start(params, numParams);
for (int i = 0; i < numParams; i++)
{
- exceptionRecord->ExceptionInformation[i] = va_arg(params, size_t);
+ exceptionRecord.ExceptionInformation[i] = va_arg(params, size_t);
}
// Pre-populate context with data from current frame, because ucontext doesn't have some data (e.g. SS register)
// which is required for restoring context
- RtlCaptureContext(contextRecord);
+ RtlCaptureContext(&contextRecord);
ULONG contextFlags = CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_FLOATING_POINT;
@@ -881,7 +879,7 @@ static bool common_signal_handler(int code, siginfo_t *siginfo, void *sigcontext
// Fill context record with required information. from pal.h:
// On non-Win32 platforms, the CONTEXT pointer in the
// PEXCEPTION_POINTERS will contain at least the CONTEXT_CONTROL registers.
- CONTEXTFromNativeContext(ucontext, contextRecord, contextFlags);
+ CONTEXTFromNativeContext(ucontext, &contextRecord, contextFlags);
/* Unmask signal so we can receive it again */
sigemptyset(&signal_set);
@@ -892,17 +890,17 @@ static bool common_signal_handler(int code, siginfo_t *siginfo, void *sigcontext
ASSERT("pthread_sigmask failed; error number is %d\n", sigmaskRet);
}
- contextRecord->ContextFlags |= CONTEXT_EXCEPTION_ACTIVE;
+ contextRecord.ContextFlags |= CONTEXT_EXCEPTION_ACTIVE;
- memcpy_s(&signalContextRecord, sizeof(CONTEXT), contextRecord, sizeof(CONTEXT));
+ memcpy_s(&signalContextRecord, sizeof(CONTEXT), &contextRecord, sizeof(CONTEXT));
// The exception object takes ownership of the exceptionRecord and contextRecord
- PAL_SEHException exception(exceptionRecord, contextRecord);
+ PAL_SEHException exception(&exceptionRecord, &contextRecord, true);
if (SEHProcessException(&exception))
{
// Exception handling may have modified the context, so update it.
- CONTEXTToNativeContext(contextRecord, ucontext);
+ CONTEXTToNativeContext(&contextRecord, ucontext);
return true;
}