secured access to buffers in NtWaitForSingleObject(), NtWaitForMultipleObjects() and NtSignalAndWaitForSingleObject() Modified: trunk/reactos/include/ntos/zw.h Modified: trunk/reactos/ntoskrnl/ke/wait.c Modified: trunk/reactos/w32api/include/ddk/winddk.h _____
Modified: trunk/reactos/include/ntos/zw.h --- trunk/reactos/include/ntos/zw.h 2005-02-14 21:41:49 UTC (rev 13578) +++ trunk/reactos/include/ntos/zw.h 2005-02-14 22:50:15 UTC (rev 13579) @@ -4423,28 +4423,28 @@
/* * FUNCTION: Signals an object and wait for an other one. * ARGUMENTS: - * SignalObject = Handle to the object that should be signaled - * WaitObject = Handle to the object that should be waited for + * ObjectHandleToSignal = Handle to the object that should be signaled + * WaitableObjectHandle = Handle to the object that should be waited for * Alertable = True if the wait is alertable - * Time = The time to wait + * TimeOut = The time to wait * RETURNS: Status */ NTSTATUS STDCALL NtSignalAndWaitForSingleObject( - IN HANDLE SignalObject, - IN HANDLE WaitObject, + IN HANDLE ObjectHandleToSignal, + IN HANDLE WaitableObjectHandle, IN BOOLEAN Alertable, - IN PLARGE_INTEGER Time + IN PLARGE_INTEGER TimeOut OPTIONAL );
NTSTATUS STDCALL NtSignalAndWaitForSingleObject( - IN HANDLE SignalObject, - IN HANDLE WaitObject, + IN HANDLE ObjectHandleToSignal, + IN HANDLE WaitableObjectHandle, IN BOOLEAN Alertable, - IN PLARGE_INTEGER Time + IN PLARGE_INTEGER TimeOut OPTIONAL );
/* @@ -4651,9 +4651,9 @@ /* * FUNCTION: Waits for an object to become signalled. * ARGUMENTS: - * Object = The object handle + * ObjectHandle = The object handle * Alertable = If true the wait is alertable. - * Time = The maximum wait time. + * TimeOut = The maximum wait time. * REMARKS: * This function maps to the win32 WaitForSingleObjectEx. * RETURNS: Status @@ -4661,17 +4661,17 @@ NTSTATUS STDCALL NtWaitForSingleObject ( - IN HANDLE Object, + IN HANDLE ObjectHandle, IN BOOLEAN Alertable, - IN PLARGE_INTEGER Time + IN PLARGE_INTEGER TimeOut OPTIONAL );
NTSTATUS STDCALL ZwWaitForSingleObject ( - IN HANDLE Object, + IN HANDLE ObjectHandle, IN BOOLEAN Alertable, - IN PLARGE_INTEGER Time + IN PLARGE_INTEGER TimeOut OPTIONAL );
/* --- EVENT PAIR OBJECT --- */ @@ -5583,11 +5583,11 @@ /* * FUNCTION: Waits for multiple objects to become signalled. * ARGUMENTS: - * Count = The number of objects - * Object = The array of object handles + * ObjectCount = The number of objects + * ObjectsArray = The array of object handles * WaitType = Can be one of the values UserMode or KernelMode * Alertable = If true the wait is alertable. - * Time = The maximum wait time. + * TimeOut = The maximum wait time. * REMARKS: * This function maps to the win32 WaitForMultipleObjectEx. * RETURNS: Status @@ -5595,11 +5595,11 @@ NTSTATUS STDCALL NtWaitForMultipleObjects ( - IN ULONG Count, - IN HANDLE Object[], + IN ULONG ObjectCount, + IN PHANDLE ObjectsArray, IN WAIT_TYPE WaitType, IN BOOLEAN Alertable, - IN PLARGE_INTEGER Time + IN PLARGE_INTEGER TimeOut OPTIONAL );
@@ -6357,11 +6357,11 @@ /* * FUNCTION: Waits for multiple objects to become signalled. * ARGUMENTS: - * Count = The number of objects - * Object = The array of object handles + * ObjectCount = The number of objects + * ObjectsArray = The array of object handles * WaitType = Can be one of the values UserMode or KernelMode * Alertable = If true the wait is alertable. - * Time = The maximum wait time. + * TimeOut = The maximum wait time. * REMARKS: * This function maps to the win32 WaitForMultipleObjectEx. * RETURNS: Status @@ -6369,11 +6369,11 @@ NTSTATUS STDCALL ZwWaitForMultipleObjects ( - IN ULONG Count, - IN HANDLE Object[], + IN ULONG ObjectCount, + IN PHANDLE ObjectsArray, IN WAIT_TYPE WaitType, IN BOOLEAN Alertable, - IN PLARGE_INTEGER Time + IN PLARGE_INTEGER TimeOut OPTIONAL );
/* _____
Modified: trunk/reactos/ntoskrnl/ke/wait.c --- trunk/reactos/ntoskrnl/ke/wait.c 2005-02-14 21:41:49 UTC (rev 13578) +++ trunk/reactos/ntoskrnl/ke/wait.c 2005-02-14 22:50:15 UTC (rev 13579) @@ -785,45 +785,71 @@
}
NTSTATUS STDCALL -NtWaitForMultipleObjects(IN ULONG Count, - IN HANDLE Object [], +NtWaitForMultipleObjects(IN ULONG ObjectCount, + IN PHANDLE ObjectsArray, IN WAIT_TYPE WaitType, IN BOOLEAN Alertable, - IN PLARGE_INTEGER UnsafeTime) + IN PLARGE_INTEGER TimeOut OPTIONAL) { KWAIT_BLOCK WaitBlockArray[MAXIMUM_WAIT_OBJECTS]; + HANDLE SafeObjectsArray[MAXIMUM_WAIT_OBJECTS]; PVOID ObjectPtrArray[MAXIMUM_WAIT_OBJECTS]; - NTSTATUS Status; ULONG i, j; - KPROCESSOR_MODE WaitMode; - LARGE_INTEGER Time; + KPROCESSOR_MODE PreviousMode; + LARGE_INTEGER SafeTimeOut; + NTSTATUS Status = STATUS_SUCCESS;
- DPRINT("NtWaitForMultipleObjects(Count %lu Object[] %x, Alertable %d, " - "Time %x)\n", Count,Object,Alertable,Time); + DPRINT("NtWaitForMultipleObjects(ObjectCount %lu ObjectsArray[] %x, Alertable %d, " + "TimeOut %x)\n", ObjectCount,ObjectsArray,Alertable,TimeOut);
- if (Count > MAXIMUM_WAIT_OBJECTS) + PreviousMode = ExGetPreviousMode(); + + if (ObjectCount > MAXIMUM_WAIT_OBJECTS) return STATUS_UNSUCCESSFUL; - if (0 == Count) + if (0 == ObjectCount) return STATUS_INVALID_PARAMETER;
- if (UnsafeTime) + if(PreviousMode != KernelMode) + { + _SEH_TRY { - Status = MmCopyFromCaller(&Time, UnsafeTime, sizeof(LARGE_INTEGER)); - if (!NT_SUCCESS(Status)) - { - return(Status); - } + ProbeForRead(ObjectsArray, + ObjectCount * sizeof(ObjectsArray[0]), + sizeof(ULONG)); + /* make a copy so we don't have to guard with SEH later and keep track of + what objects we referenced in case dereferencing pointers suddenly fails */ + RtlCopyMemory(SafeObjectsArray, ObjectsArray, ObjectCount * sizeof(ObjectsArray[0])); + ObjectsArray = SafeObjectsArray; + + if(TimeOut != NULL) + { + ProbeForRead(TimeOut, + sizeof(LARGE_INTEGER), + sizeof(ULONG)); + /* make a local copy of the timeout on the stack */ + SafeTimeOut = *TimeOut; + TimeOut = &SafeTimeOut; + } } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + + if(!NT_SUCCESS(Status)) + { + return Status; + } + }
- WaitMode = ExGetPreviousMode(); - /* reference all objects */ - for (i = 0; i < Count; i++) + for (i = 0; i < ObjectCount; i++) { - Status = ObReferenceObjectByHandle(Object[i], + Status = ObReferenceObjectByHandle(ObjectsArray[i], SYNCHRONIZE, NULL, - WaitMode, + PreviousMode, &ObjectPtrArray[i], NULL); if (!NT_SUCCESS(Status) || !KiIsObjectWaitable(ObjectPtrArray[i])) @@ -845,17 +871,17 @@ } }
- Status = KeWaitForMultipleObjects(Count, + Status = KeWaitForMultipleObjects(ObjectCount, ObjectPtrArray, WaitType, UserRequest, - WaitMode, + PreviousMode, Alertable, - UnsafeTime ? &Time : NULL, + TimeOut, WaitBlockArray);
/* dereference all objects */ - for (i = 0; i < Count; i++) + for (i = 0; i < ObjectCount; i++) { ObDereferenceObject(ObjectPtrArray[i]); } @@ -868,33 +894,47 @@ * @implemented */ NTSTATUS STDCALL -NtWaitForSingleObject(IN HANDLE Object, +NtWaitForSingleObject(IN HANDLE ObjectHandle, IN BOOLEAN Alertable, - IN PLARGE_INTEGER UnsafeTime) + IN PLARGE_INTEGER TimeOut OPTIONAL) { PVOID ObjectPtr; - NTSTATUS Status; - KPROCESSOR_MODE WaitMode; - LARGE_INTEGER Time; + KPROCESSOR_MODE PreviousMode; + LARGE_INTEGER SafeTimeOut; + NTSTATUS Status = STATUS_SUCCESS;
- DPRINT("NtWaitForSingleObject(Object %x, Alertable %d, Time %x)\n", - Object,Alertable,Time); + DPRINT("NtWaitForSingleObject(ObjectHandle %x, Alertable %d, TimeOut %x)\n", + ObjectHandle,Alertable,TimeOut);
- if (UnsafeTime) + PreviousMode = ExGetPreviousMode(); + + if(TimeOut != NULL && PreviousMode != KernelMode) + { + _SEH_TRY { - Status = MmCopyFromCaller(&Time, UnsafeTime, sizeof(LARGE_INTEGER)); - if (!NT_SUCCESS(Status)) - { - return(Status); - } + ProbeForRead(TimeOut, + sizeof(LARGE_INTEGER), + sizeof(ULONG)); + /* make a copy on the stack */ + SafeTimeOut = *TimeOut; + TimeOut = &SafeTimeOut; } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + + if(!NT_SUCCESS(Status)) + { + return Status; + } + }
- WaitMode = ExGetPreviousMode(); - - Status = ObReferenceObjectByHandle(Object, + Status = ObReferenceObjectByHandle(ObjectHandle, SYNCHRONIZE, NULL, - WaitMode, + PreviousMode, &ObjectPtr, NULL); if (!NT_SUCCESS(Status)) @@ -911,9 +951,9 @@ { Status = KeWaitForSingleObject(ObjectPtr, UserRequest, - WaitMode, + PreviousMode, Alertable, - UnsafeTime ? &Time : NULL); + TimeOut); }
ObDereferenceObject(ObjectPtr); @@ -923,22 +963,47 @@
NTSTATUS STDCALL -NtSignalAndWaitForSingleObject(IN HANDLE SignalObject, - IN HANDLE WaitObject, +NtSignalAndWaitForSingleObject(IN HANDLE ObjectHandleToSignal, + IN HANDLE WaitableObjectHandle, IN BOOLEAN Alertable, - IN PLARGE_INTEGER Time) + IN PLARGE_INTEGER TimeOut OPTIONAL) { - KPROCESSOR_MODE WaitMode; + KPROCESSOR_MODE PreviousMode; DISPATCHER_HEADER* hdr; PVOID SignalObj; PVOID WaitObj; - NTSTATUS Status; + LARGE_INTEGER SafeTimeOut; + NTSTATUS Status = STATUS_SUCCESS;
- WaitMode = ExGetPreviousMode(); - Status = ObReferenceObjectByHandle(SignalObject, + PreviousMode = ExGetPreviousMode(); + + if(TimeOut != NULL && PreviousMode != KernelMode) + { + _SEH_TRY + { + ProbeForRead(TimeOut, + sizeof(LARGE_INTEGER), + sizeof(ULONG)); + /* make a copy on the stack */ + SafeTimeOut = *TimeOut; + TimeOut = &SafeTimeOut; + } + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + + if(!NT_SUCCESS(Status)) + { + return Status; + } + } + + Status = ObReferenceObjectByHandle(ObjectHandleToSignal, 0, NULL, - WaitMode, + PreviousMode, &SignalObj, NULL); if (!NT_SUCCESS(Status)) @@ -946,10 +1011,10 @@ return Status; }
- Status = ObReferenceObjectByHandle(WaitObject, + Status = ObReferenceObjectByHandle(WaitableObjectHandle, SYNCHRONIZE, NULL, - WaitMode, + PreviousMode, &WaitObj, NULL); if (!NT_SUCCESS(Status)) @@ -988,9 +1053,9 @@
Status = KeWaitForSingleObject(WaitObj, UserRequest, - WaitMode, + PreviousMode, Alertable, - Time); + TimeOut);
ObDereferenceObject(SignalObj); ObDereferenceObject(WaitObj); _____
Modified: trunk/reactos/w32api/include/ddk/winddk.h --- trunk/reactos/w32api/include/ddk/winddk.h 2005-02-14 21:41:49 UTC (rev 13578) +++ trunk/reactos/w32api/include/ddk/winddk.h 2005-02-14 22:50:15 UTC (rev 13579) @@ -9131,17 +9131,17 @@
NTSTATUS DDKAPI NtWaitForSingleObject( - IN HANDLE Object, + IN HANDLE ObjectHandle, IN BOOLEAN Alertable, - IN PLARGE_INTEGER Time); + IN PLARGE_INTEGER TimeOut OPTIONAL);
NTOSAPI NTSTATUS DDKAPI ZwWaitForSingleObject( - IN HANDLE Object, + IN HANDLE ObjectHandle, IN BOOLEAN Alertable, - IN PLARGE_INTEGER Time); + IN PLARGE_INTEGER TimeOut OPTIONAL);
NTOSAPI NTSTATUS