From 79dd48516a8474d2b089d42e2c0382172bc835ad Mon Sep 17 00:00:00 2001 From: Stefan Ginsberg Date: Mon, 28 Sep 2015 09:01:11 +0000 Subject: [PATCH] [NTOS] Fix the Ob wait system calls to only catch the exceptions that are expected to be raised by the Ke wait functions (and not potentially silently catching *any* exception and corrupting everything in the process). Also fixup some code logic. SEH Mega Fixup 1/??? svn path=/trunk/; revision=69393 --- reactos/ntoskrnl/ob/obwait.c | 100 ++++++++++++++++++++++------------- 1 file changed, 62 insertions(+), 38 deletions(-) diff --git a/reactos/ntoskrnl/ob/obwait.c b/reactos/ntoskrnl/ob/obwait.c index 081be0da406..f61c9ba9bdd 100644 --- a/reactos/ntoskrnl/ob/obwait.c +++ b/reactos/ntoskrnl/ob/obwait.c @@ -49,12 +49,12 @@ NtWaitForMultipleObjects(IN ULONG ObjectCount, IN BOOLEAN Alertable, IN PLARGE_INTEGER TimeOut OPTIONAL) { - PKWAIT_BLOCK WaitBlockArray = NULL; + PKWAIT_BLOCK WaitBlockArray; HANDLE Handles[MAXIMUM_WAIT_OBJECTS], KernelHandle; PVOID Objects[MAXIMUM_WAIT_OBJECTS]; PVOID WaitObjects[MAXIMUM_WAIT_OBJECTS]; - ULONG i = 0, ReferencedObjects = 0, j; - KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); + ULONG i, ReferencedObjects, j; + KPROCESSOR_MODE PreviousMode; LARGE_INTEGER SafeTimeOut; BOOLEAN LockInUse; PHANDLE_TABLE_ENTRY HandleEntry; @@ -65,31 +65,26 @@ NtWaitForMultipleObjects(IN ULONG ObjectCount, NTSTATUS Status; PAGED_CODE(); - /* Enter a critical region since we'll play with handles */ - LockInUse = TRUE; - KeEnterCriticalRegion(); - /* Check for valid Object Count */ if ((ObjectCount > MAXIMUM_WAIT_OBJECTS) || !(ObjectCount)) { /* Fail */ - Status = STATUS_INVALID_PARAMETER_1; - goto Quickie; + return STATUS_INVALID_PARAMETER_1; } /* Check for valid Wait Type */ if ((WaitType != WaitAll) && (WaitType != WaitAny)) { /* Fail */ - Status = STATUS_INVALID_PARAMETER_3; - goto Quickie; + return STATUS_INVALID_PARAMETER_3; } - /* Enter SEH */ - _SEH2_TRY + /* Enter SEH for user mode */ + PreviousMode = ExGetPreviousMode(); + if (PreviousMode != KernelMode) { - /* Check if the call came from user mode */ - if (PreviousMode != KernelMode) + /* Enter SEH */ + _SEH2_TRY { /* Check if we have a timeout */ if (TimeOut) @@ -103,24 +98,30 @@ NtWaitForMultipleObjects(IN ULONG ObjectCount, ProbeForRead(HandleArray, ObjectCount * sizeof(HANDLE), sizeof(HANDLE)); - } - /* - * Make a copy so we don't have to guard with SEH later and keep - * track of what objects we referenced if dereferencing pointers - * suddenly fails - */ + /* + * Make a copy so we don't have to guard with SEH later and keep + * track of what objects we referenced if dereferencing pointers + * suddenly fails + */ + RtlCopyMemory(Handles, + HandleArray, + ObjectCount * sizeof(HANDLE)); + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + /* Return the exception code */ + _SEH2_YIELD(return _SEH2_GetExceptionCode()); + } + _SEH2_END; + } + else + { + /* This is kernel mode, no need to wrap in SEH */ RtlCopyMemory(Handles, HandleArray, ObjectCount * sizeof(HANDLE)); } - _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) - { - /* Return the exception code */ - Status = _SEH2_GetExceptionCode(); - _SEH2_YIELD(goto Quickie); - } - _SEH2_END; /* Check if we can use the internal Wait Array */ if (ObjectCount > THREAD_WAIT_OBJECTS) @@ -133,12 +134,22 @@ NtWaitForMultipleObjects(IN ULONG ObjectCount, if (!WaitBlockArray) { /* Fail */ - Status = STATUS_INSUFFICIENT_RESOURCES; - goto Quickie; + return STATUS_INSUFFICIENT_RESOURCES; } } + else + { + /* No need for the array */ + WaitBlockArray = NULL; + } + + /* Enter a critical region since we'll play with handles */ + LockInUse = TRUE; + KeEnterCriticalRegion(); /* Start the loop */ + i = 0; + ReferencedObjects = 0; do { /* Use the right Executive Handle */ @@ -240,7 +251,7 @@ NtWaitForMultipleObjects(IN ULONG ObjectCount, } while (i < ObjectCount); } - /* Now we can finally wait. Use SEH since it can raise an exception */ + /* Now we can finally wait. Always use SEH since it can raise an exception */ _SEH2_TRY { /* We're done playing with handles */ @@ -257,7 +268,9 @@ NtWaitForMultipleObjects(IN ULONG ObjectCount, TimeOut, WaitBlockArray); } - _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + _SEH2_EXCEPT((_SEH2_GetExceptionCode() == STATUS_MUTANT_LIMIT_EXCEEDED) ? + EXCEPTION_EXECUTE_HANDLER : + EXCEPTION_CONTINUE_SEARCH) { /* Get the exception code */ Status = _SEH2_GetExceptionCode(); @@ -358,11 +371,12 @@ NtWaitForSingleObject(IN HANDLE ObjectHandle, IN PLARGE_INTEGER TimeOut OPTIONAL) { PVOID Object, WaitableObject; - KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); + KPROCESSOR_MODE PreviousMode; LARGE_INTEGER SafeTimeOut; NTSTATUS Status; /* Check if we came with a timeout from user mode */ + PreviousMode = ExGetPreviousMode(); if ((TimeOut) && (PreviousMode != KernelMode)) { /* Enter SEH for proving */ @@ -410,7 +424,9 @@ NtWaitForSingleObject(IN HANDLE ObjectHandle, Alertable, TimeOut); } - _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + _SEH2_EXCEPT((_SEH2_GetExceptionCode() == STATUS_MUTANT_LIMIT_EXCEEDED) ? + EXCEPTION_EXECUTE_HANDLER : + EXCEPTION_CONTINUE_SEARCH) { /* Get the exception code */ Status = _SEH2_GetExceptionCode(); @@ -459,7 +475,7 @@ NtSignalAndWaitForSingleObject(IN HANDLE ObjectHandleToSignal, IN BOOLEAN Alertable, IN PLARGE_INTEGER TimeOut OPTIONAL) { - KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); + KPROCESSOR_MODE PreviousMode; POBJECT_TYPE Type; PVOID SignalObj, WaitObj, WaitableObject; LARGE_INTEGER SafeTimeOut; @@ -467,6 +483,7 @@ NtSignalAndWaitForSingleObject(IN HANDLE ObjectHandleToSignal, NTSTATUS Status; /* Check if we came with a timeout from user mode */ + PreviousMode = ExGetPreviousMode(); if ((TimeOut) && (PreviousMode != KernelMode)) { /* Enter SEH for probing */ @@ -542,7 +559,10 @@ NtSignalAndWaitForSingleObject(IN HANDLE ObjectHandleToSignal, /* Release the mutant */ KeReleaseMutant(SignalObj, MUTANT_INCREMENT, FALSE, TRUE); } - _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + _SEH2_EXCEPT(((_SEH2_GetExceptionCode() == STATUS_ABANDONED) || + (_SEH2_GetExceptionCode() == STATUS_MUTANT_NOT_OWNED)) ? + EXCEPTION_EXECUTE_HANDLER : + EXCEPTION_CONTINUE_SEARCH) { /* Get the exception code */ Status = _SEH2_GetExceptionCode(); @@ -566,7 +586,9 @@ NtSignalAndWaitForSingleObject(IN HANDLE ObjectHandleToSignal, /* Release the semaphore */ KeReleaseSemaphore(SignalObj, SEMAPHORE_INCREMENT, 1, TRUE); } - _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + _SEH2_EXCEPT((_SEH2_GetExceptionCode() == STATUS_SEMAPHORE_LIMIT_EXCEEDED) ? + EXCEPTION_EXECUTE_HANDLER : + EXCEPTION_CONTINUE_SEARCH) { /* Get the exception code */ Status = _SEH2_GetExceptionCode(); @@ -592,7 +614,9 @@ NtSignalAndWaitForSingleObject(IN HANDLE ObjectHandleToSignal, Alertable, TimeOut); } - _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + _SEH2_EXCEPT((_SEH2_GetExceptionCode() == STATUS_MUTANT_LIMIT_EXCEEDED) ? + EXCEPTION_EXECUTE_HANDLER : + EXCEPTION_CONTINUE_SEARCH) { /* Get the exception code */ Status = _SEH2_GetExceptionCode();