[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
This commit is contained in:
Stefan Ginsberg 2015-09-28 09:01:11 +00:00
parent 2f08cf3f2a
commit 79dd48516a

View file

@ -49,12 +49,12 @@ NtWaitForMultipleObjects(IN ULONG ObjectCount,
IN BOOLEAN Alertable, IN BOOLEAN Alertable,
IN PLARGE_INTEGER TimeOut OPTIONAL) IN PLARGE_INTEGER TimeOut OPTIONAL)
{ {
PKWAIT_BLOCK WaitBlockArray = NULL; PKWAIT_BLOCK WaitBlockArray;
HANDLE Handles[MAXIMUM_WAIT_OBJECTS], KernelHandle; HANDLE Handles[MAXIMUM_WAIT_OBJECTS], KernelHandle;
PVOID Objects[MAXIMUM_WAIT_OBJECTS]; PVOID Objects[MAXIMUM_WAIT_OBJECTS];
PVOID WaitObjects[MAXIMUM_WAIT_OBJECTS]; PVOID WaitObjects[MAXIMUM_WAIT_OBJECTS];
ULONG i = 0, ReferencedObjects = 0, j; ULONG i, ReferencedObjects, j;
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); KPROCESSOR_MODE PreviousMode;
LARGE_INTEGER SafeTimeOut; LARGE_INTEGER SafeTimeOut;
BOOLEAN LockInUse; BOOLEAN LockInUse;
PHANDLE_TABLE_ENTRY HandleEntry; PHANDLE_TABLE_ENTRY HandleEntry;
@ -65,31 +65,26 @@ NtWaitForMultipleObjects(IN ULONG ObjectCount,
NTSTATUS Status; NTSTATUS Status;
PAGED_CODE(); PAGED_CODE();
/* Enter a critical region since we'll play with handles */
LockInUse = TRUE;
KeEnterCriticalRegion();
/* Check for valid Object Count */ /* Check for valid Object Count */
if ((ObjectCount > MAXIMUM_WAIT_OBJECTS) || !(ObjectCount)) if ((ObjectCount > MAXIMUM_WAIT_OBJECTS) || !(ObjectCount))
{ {
/* Fail */ /* Fail */
Status = STATUS_INVALID_PARAMETER_1; return STATUS_INVALID_PARAMETER_1;
goto Quickie;
} }
/* Check for valid Wait Type */ /* Check for valid Wait Type */
if ((WaitType != WaitAll) && (WaitType != WaitAny)) if ((WaitType != WaitAll) && (WaitType != WaitAny))
{ {
/* Fail */ /* Fail */
Status = STATUS_INVALID_PARAMETER_3; return STATUS_INVALID_PARAMETER_3;
goto Quickie;
} }
/* Enter SEH for user mode */
PreviousMode = ExGetPreviousMode();
if (PreviousMode != KernelMode)
{
/* Enter SEH */ /* Enter SEH */
_SEH2_TRY _SEH2_TRY
{
/* Check if the call came from user mode */
if (PreviousMode != KernelMode)
{ {
/* Check if we have a timeout */ /* Check if we have a timeout */
if (TimeOut) if (TimeOut)
@ -103,7 +98,6 @@ NtWaitForMultipleObjects(IN ULONG ObjectCount,
ProbeForRead(HandleArray, ProbeForRead(HandleArray,
ObjectCount * sizeof(HANDLE), ObjectCount * sizeof(HANDLE),
sizeof(HANDLE)); sizeof(HANDLE));
}
/* /*
* Make a copy so we don't have to guard with SEH later and keep * Make a copy so we don't have to guard with SEH later and keep
@ -117,10 +111,17 @@ NtWaitForMultipleObjects(IN ULONG ObjectCount,
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
{ {
/* Return the exception code */ /* Return the exception code */
Status = _SEH2_GetExceptionCode(); _SEH2_YIELD(return _SEH2_GetExceptionCode());
_SEH2_YIELD(goto Quickie);
} }
_SEH2_END; _SEH2_END;
}
else
{
/* This is kernel mode, no need to wrap in SEH */
RtlCopyMemory(Handles,
HandleArray,
ObjectCount * sizeof(HANDLE));
}
/* Check if we can use the internal Wait Array */ /* Check if we can use the internal Wait Array */
if (ObjectCount > THREAD_WAIT_OBJECTS) if (ObjectCount > THREAD_WAIT_OBJECTS)
@ -133,12 +134,22 @@ NtWaitForMultipleObjects(IN ULONG ObjectCount,
if (!WaitBlockArray) if (!WaitBlockArray)
{ {
/* Fail */ /* Fail */
Status = STATUS_INSUFFICIENT_RESOURCES; return STATUS_INSUFFICIENT_RESOURCES;
goto Quickie;
} }
} }
else
{
/* No need for the array */
WaitBlockArray = NULL;
}
/* Enter a critical region since we'll play with handles */
LockInUse = TRUE;
KeEnterCriticalRegion();
/* Start the loop */ /* Start the loop */
i = 0;
ReferencedObjects = 0;
do do
{ {
/* Use the right Executive Handle */ /* Use the right Executive Handle */
@ -240,7 +251,7 @@ NtWaitForMultipleObjects(IN ULONG ObjectCount,
} while (i < 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 _SEH2_TRY
{ {
/* We're done playing with handles */ /* We're done playing with handles */
@ -257,7 +268,9 @@ NtWaitForMultipleObjects(IN ULONG ObjectCount,
TimeOut, TimeOut,
WaitBlockArray); WaitBlockArray);
} }
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) _SEH2_EXCEPT((_SEH2_GetExceptionCode() == STATUS_MUTANT_LIMIT_EXCEEDED) ?
EXCEPTION_EXECUTE_HANDLER :
EXCEPTION_CONTINUE_SEARCH)
{ {
/* Get the exception code */ /* Get the exception code */
Status = _SEH2_GetExceptionCode(); Status = _SEH2_GetExceptionCode();
@ -358,11 +371,12 @@ NtWaitForSingleObject(IN HANDLE ObjectHandle,
IN PLARGE_INTEGER TimeOut OPTIONAL) IN PLARGE_INTEGER TimeOut OPTIONAL)
{ {
PVOID Object, WaitableObject; PVOID Object, WaitableObject;
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); KPROCESSOR_MODE PreviousMode;
LARGE_INTEGER SafeTimeOut; LARGE_INTEGER SafeTimeOut;
NTSTATUS Status; NTSTATUS Status;
/* Check if we came with a timeout from user mode */ /* Check if we came with a timeout from user mode */
PreviousMode = ExGetPreviousMode();
if ((TimeOut) && (PreviousMode != KernelMode)) if ((TimeOut) && (PreviousMode != KernelMode))
{ {
/* Enter SEH for proving */ /* Enter SEH for proving */
@ -410,7 +424,9 @@ NtWaitForSingleObject(IN HANDLE ObjectHandle,
Alertable, Alertable,
TimeOut); TimeOut);
} }
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) _SEH2_EXCEPT((_SEH2_GetExceptionCode() == STATUS_MUTANT_LIMIT_EXCEEDED) ?
EXCEPTION_EXECUTE_HANDLER :
EXCEPTION_CONTINUE_SEARCH)
{ {
/* Get the exception code */ /* Get the exception code */
Status = _SEH2_GetExceptionCode(); Status = _SEH2_GetExceptionCode();
@ -459,7 +475,7 @@ NtSignalAndWaitForSingleObject(IN HANDLE ObjectHandleToSignal,
IN BOOLEAN Alertable, IN BOOLEAN Alertable,
IN PLARGE_INTEGER TimeOut OPTIONAL) IN PLARGE_INTEGER TimeOut OPTIONAL)
{ {
KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); KPROCESSOR_MODE PreviousMode;
POBJECT_TYPE Type; POBJECT_TYPE Type;
PVOID SignalObj, WaitObj, WaitableObject; PVOID SignalObj, WaitObj, WaitableObject;
LARGE_INTEGER SafeTimeOut; LARGE_INTEGER SafeTimeOut;
@ -467,6 +483,7 @@ NtSignalAndWaitForSingleObject(IN HANDLE ObjectHandleToSignal,
NTSTATUS Status; NTSTATUS Status;
/* Check if we came with a timeout from user mode */ /* Check if we came with a timeout from user mode */
PreviousMode = ExGetPreviousMode();
if ((TimeOut) && (PreviousMode != KernelMode)) if ((TimeOut) && (PreviousMode != KernelMode))
{ {
/* Enter SEH for probing */ /* Enter SEH for probing */
@ -542,7 +559,10 @@ NtSignalAndWaitForSingleObject(IN HANDLE ObjectHandleToSignal,
/* Release the mutant */ /* Release the mutant */
KeReleaseMutant(SignalObj, MUTANT_INCREMENT, FALSE, TRUE); 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 */ /* Get the exception code */
Status = _SEH2_GetExceptionCode(); Status = _SEH2_GetExceptionCode();
@ -566,7 +586,9 @@ NtSignalAndWaitForSingleObject(IN HANDLE ObjectHandleToSignal,
/* Release the semaphore */ /* Release the semaphore */
KeReleaseSemaphore(SignalObj, SEMAPHORE_INCREMENT, 1, TRUE); 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 */ /* Get the exception code */
Status = _SEH2_GetExceptionCode(); Status = _SEH2_GetExceptionCode();
@ -592,7 +614,9 @@ NtSignalAndWaitForSingleObject(IN HANDLE ObjectHandleToSignal,
Alertable, Alertable,
TimeOut); TimeOut);
} }
_SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) _SEH2_EXCEPT((_SEH2_GetExceptionCode() == STATUS_MUTANT_LIMIT_EXCEEDED) ?
EXCEPTION_EXECUTE_HANDLER :
EXCEPTION_CONTINUE_SEARCH)
{ {
/* Get the exception code */ /* Get the exception code */
Status = _SEH2_GetExceptionCode(); Status = _SEH2_GetExceptionCode();