From f4c9f962051ea4cd6db910115e19848011a41357 Mon Sep 17 00:00:00 2001 From: Thomas Bluemel Date: Mon, 14 Feb 2005 22:50:15 +0000 Subject: [PATCH] secured access to buffers in NtWaitForSingleObject(), NtWaitForMultipleObjects() and NtSignalAndWaitForSingleObject() svn path=/trunk/; revision=13579 --- reactos/include/ntos/zw.h | 54 ++++----- reactos/ntoskrnl/ke/wait.c | 177 +++++++++++++++++++--------- reactos/w32api/include/ddk/winddk.h | 8 +- 3 files changed, 152 insertions(+), 87 deletions(-) diff --git a/reactos/include/ntos/zw.h b/reactos/include/ntos/zw.h index 5d898bde765..37a143d35cb 100755 --- a/reactos/include/ntos/zw.h +++ b/reactos/include/ntos/zw.h @@ -4423,28 +4423,28 @@ ZwShutdownSystem( /* * 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 @@ ZwWriteVirtualMemory( /* * 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 @@ ZwWriteVirtualMemory( 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 @@ NtUnlockVirtualMemory( /* * 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 @@ NtUnlockVirtualMemory( 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 @@ ZwUnlockVirtualMemory( /* * 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 @@ ZwUnlockVirtualMemory( 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 ); /* diff --git a/reactos/ntoskrnl/ke/wait.c b/reactos/ntoskrnl/ke/wait.c index 8e4da0f3ae2..a6575e9bb88 100644 --- a/reactos/ntoskrnl/ke/wait.c +++ b/reactos/ntoskrnl/ke/wait.c @@ -785,45 +785,71 @@ VOID KeInitializeDispatcher(VOID) } 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; + } } - - WaitMode = ExGetPreviousMode(); + _SEH_HANDLE + { + Status = _SEH_GetExceptionCode(); + } + _SEH_END; + + if(!NT_SUCCESS(Status)) + { + return Status; + } + } /* 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 @@ NtWaitForMultipleObjects(IN ULONG Count, } } - 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 @@ NtWaitForMultipleObjects(IN ULONG Count, * @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 @@ NtWaitForSingleObject(IN HANDLE Object, { Status = KeWaitForSingleObject(ObjectPtr, UserRequest, - WaitMode, + PreviousMode, Alertable, - UnsafeTime ? &Time : NULL); + TimeOut); } ObDereferenceObject(ObjectPtr); @@ -923,22 +963,47 @@ NtWaitForSingleObject(IN HANDLE Object, 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 @@ NtSignalAndWaitForSingleObject(IN HANDLE SignalObject, return Status; } - Status = ObReferenceObjectByHandle(WaitObject, + Status = ObReferenceObjectByHandle(WaitableObjectHandle, SYNCHRONIZE, NULL, - WaitMode, + PreviousMode, &WaitObj, NULL); if (!NT_SUCCESS(Status)) @@ -988,9 +1053,9 @@ NtSignalAndWaitForSingleObject(IN HANDLE SignalObject, Status = KeWaitForSingleObject(WaitObj, UserRequest, - WaitMode, + PreviousMode, Alertable, - Time); + TimeOut); ObDereferenceObject(SignalObj); ObDereferenceObject(WaitObj); diff --git a/reactos/w32api/include/ddk/winddk.h b/reactos/w32api/include/ddk/winddk.h index 65b707d0dd5..a75c0ccca0f 100644 --- a/reactos/w32api/include/ddk/winddk.h +++ b/reactos/w32api/include/ddk/winddk.h @@ -9131,17 +9131,17 @@ NTOSAPI 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