secured access to buffers in NtWaitForSingleObject(), NtWaitForMultipleObjects() and NtSignalAndWaitForSingleObject()

svn path=/trunk/; revision=13579
This commit is contained in:
Thomas Bluemel 2005-02-14 22:50:15 +00:00
parent eafae64526
commit f4c9f96205
3 changed files with 152 additions and 87 deletions

View file

@ -4423,28 +4423,28 @@ ZwShutdownSystem(
/* /*
* FUNCTION: Signals an object and wait for an other one. * FUNCTION: Signals an object and wait for an other one.
* ARGUMENTS: * ARGUMENTS:
* SignalObject = Handle to the object that should be signaled * ObjectHandleToSignal = Handle to the object that should be signaled
* WaitObject = Handle to the object that should be waited for * WaitableObjectHandle = Handle to the object that should be waited for
* Alertable = True if the wait is alertable * Alertable = True if the wait is alertable
* Time = The time to wait * TimeOut = The time to wait
* RETURNS: Status * RETURNS: Status
*/ */
NTSTATUS NTSTATUS
STDCALL STDCALL
NtSignalAndWaitForSingleObject( NtSignalAndWaitForSingleObject(
IN HANDLE SignalObject, IN HANDLE ObjectHandleToSignal,
IN HANDLE WaitObject, IN HANDLE WaitableObjectHandle,
IN BOOLEAN Alertable, IN BOOLEAN Alertable,
IN PLARGE_INTEGER Time IN PLARGE_INTEGER TimeOut OPTIONAL
); );
NTSTATUS NTSTATUS
STDCALL STDCALL
NtSignalAndWaitForSingleObject( NtSignalAndWaitForSingleObject(
IN HANDLE SignalObject, IN HANDLE ObjectHandleToSignal,
IN HANDLE WaitObject, IN HANDLE WaitableObjectHandle,
IN BOOLEAN Alertable, 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. * FUNCTION: Waits for an object to become signalled.
* ARGUMENTS: * ARGUMENTS:
* Object = The object handle * ObjectHandle = The object handle
* Alertable = If true the wait is alertable. * Alertable = If true the wait is alertable.
* Time = The maximum wait time. * TimeOut = The maximum wait time.
* REMARKS: * REMARKS:
* This function maps to the win32 WaitForSingleObjectEx. * This function maps to the win32 WaitForSingleObjectEx.
* RETURNS: Status * RETURNS: Status
@ -4661,17 +4661,17 @@ ZwWriteVirtualMemory(
NTSTATUS NTSTATUS
STDCALL STDCALL
NtWaitForSingleObject ( NtWaitForSingleObject (
IN HANDLE Object, IN HANDLE ObjectHandle,
IN BOOLEAN Alertable, IN BOOLEAN Alertable,
IN PLARGE_INTEGER Time IN PLARGE_INTEGER TimeOut OPTIONAL
); );
NTSTATUS NTSTATUS
STDCALL STDCALL
ZwWaitForSingleObject ( ZwWaitForSingleObject (
IN HANDLE Object, IN HANDLE ObjectHandle,
IN BOOLEAN Alertable, IN BOOLEAN Alertable,
IN PLARGE_INTEGER Time IN PLARGE_INTEGER TimeOut OPTIONAL
); );
/* --- EVENT PAIR OBJECT --- */ /* --- EVENT PAIR OBJECT --- */
@ -5583,11 +5583,11 @@ NtUnlockVirtualMemory(
/* /*
* FUNCTION: Waits for multiple objects to become signalled. * FUNCTION: Waits for multiple objects to become signalled.
* ARGUMENTS: * ARGUMENTS:
* Count = The number of objects * ObjectCount = The number of objects
* Object = The array of object handles * ObjectsArray = The array of object handles
* WaitType = Can be one of the values UserMode or KernelMode * WaitType = Can be one of the values UserMode or KernelMode
* Alertable = If true the wait is alertable. * Alertable = If true the wait is alertable.
* Time = The maximum wait time. * TimeOut = The maximum wait time.
* REMARKS: * REMARKS:
* This function maps to the win32 WaitForMultipleObjectEx. * This function maps to the win32 WaitForMultipleObjectEx.
* RETURNS: Status * RETURNS: Status
@ -5595,11 +5595,11 @@ NtUnlockVirtualMemory(
NTSTATUS NTSTATUS
STDCALL STDCALL
NtWaitForMultipleObjects ( NtWaitForMultipleObjects (
IN ULONG Count, IN ULONG ObjectCount,
IN HANDLE Object[], IN PHANDLE ObjectsArray,
IN WAIT_TYPE WaitType, IN WAIT_TYPE WaitType,
IN BOOLEAN Alertable, 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. * FUNCTION: Waits for multiple objects to become signalled.
* ARGUMENTS: * ARGUMENTS:
* Count = The number of objects * ObjectCount = The number of objects
* Object = The array of object handles * ObjectsArray = The array of object handles
* WaitType = Can be one of the values UserMode or KernelMode * WaitType = Can be one of the values UserMode or KernelMode
* Alertable = If true the wait is alertable. * Alertable = If true the wait is alertable.
* Time = The maximum wait time. * TimeOut = The maximum wait time.
* REMARKS: * REMARKS:
* This function maps to the win32 WaitForMultipleObjectEx. * This function maps to the win32 WaitForMultipleObjectEx.
* RETURNS: Status * RETURNS: Status
@ -6369,11 +6369,11 @@ ZwUnlockVirtualMemory(
NTSTATUS NTSTATUS
STDCALL STDCALL
ZwWaitForMultipleObjects ( ZwWaitForMultipleObjects (
IN ULONG Count, IN ULONG ObjectCount,
IN HANDLE Object[], IN PHANDLE ObjectsArray,
IN WAIT_TYPE WaitType, IN WAIT_TYPE WaitType,
IN BOOLEAN Alertable, IN BOOLEAN Alertable,
IN PLARGE_INTEGER Time IN PLARGE_INTEGER TimeOut OPTIONAL
); );
/* /*

View file

@ -785,45 +785,71 @@ VOID KeInitializeDispatcher(VOID)
} }
NTSTATUS STDCALL NTSTATUS STDCALL
NtWaitForMultipleObjects(IN ULONG Count, NtWaitForMultipleObjects(IN ULONG ObjectCount,
IN HANDLE Object [], IN PHANDLE ObjectsArray,
IN WAIT_TYPE WaitType, IN WAIT_TYPE WaitType,
IN BOOLEAN Alertable, IN BOOLEAN Alertable,
IN PLARGE_INTEGER UnsafeTime) IN PLARGE_INTEGER TimeOut OPTIONAL)
{ {
KWAIT_BLOCK WaitBlockArray[MAXIMUM_WAIT_OBJECTS]; KWAIT_BLOCK WaitBlockArray[MAXIMUM_WAIT_OBJECTS];
HANDLE SafeObjectsArray[MAXIMUM_WAIT_OBJECTS];
PVOID ObjectPtrArray[MAXIMUM_WAIT_OBJECTS]; PVOID ObjectPtrArray[MAXIMUM_WAIT_OBJECTS];
NTSTATUS Status;
ULONG i, j; ULONG i, j;
KPROCESSOR_MODE WaitMode; KPROCESSOR_MODE PreviousMode;
LARGE_INTEGER Time; LARGE_INTEGER SafeTimeOut;
NTSTATUS Status = STATUS_SUCCESS;
DPRINT("NtWaitForMultipleObjects(Count %lu Object[] %x, Alertable %d, " DPRINT("NtWaitForMultipleObjects(ObjectCount %lu ObjectsArray[] %x, Alertable %d, "
"Time %x)\n", Count,Object,Alertable,Time); "TimeOut %x)\n", ObjectCount,ObjectsArray,Alertable,TimeOut);
if (Count > MAXIMUM_WAIT_OBJECTS) PreviousMode = ExGetPreviousMode();
if (ObjectCount > MAXIMUM_WAIT_OBJECTS)
return STATUS_UNSUCCESSFUL; return STATUS_UNSUCCESSFUL;
if (0 == Count) if (0 == ObjectCount)
return STATUS_INVALID_PARAMETER; return STATUS_INVALID_PARAMETER;
if (UnsafeTime) if(PreviousMode != KernelMode)
{
_SEH_TRY
{ {
Status = MmCopyFromCaller(&Time, UnsafeTime, sizeof(LARGE_INTEGER)); ProbeForRead(ObjectsArray,
if (!NT_SUCCESS(Status)) ObjectCount * sizeof(ObjectsArray[0]),
{ sizeof(ULONG));
return(Status); /* 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
WaitMode = ExGetPreviousMode(); {
Status = _SEH_GetExceptionCode();
}
_SEH_END;
if(!NT_SUCCESS(Status))
{
return Status;
}
}
/* reference all objects */ /* reference all objects */
for (i = 0; i < Count; i++) for (i = 0; i < ObjectCount; i++)
{ {
Status = ObReferenceObjectByHandle(Object[i], Status = ObReferenceObjectByHandle(ObjectsArray[i],
SYNCHRONIZE, SYNCHRONIZE,
NULL, NULL,
WaitMode, PreviousMode,
&ObjectPtrArray[i], &ObjectPtrArray[i],
NULL); NULL);
if (!NT_SUCCESS(Status) || !KiIsObjectWaitable(ObjectPtrArray[i])) if (!NT_SUCCESS(Status) || !KiIsObjectWaitable(ObjectPtrArray[i]))
@ -845,17 +871,17 @@ NtWaitForMultipleObjects(IN ULONG Count,
} }
} }
Status = KeWaitForMultipleObjects(Count, Status = KeWaitForMultipleObjects(ObjectCount,
ObjectPtrArray, ObjectPtrArray,
WaitType, WaitType,
UserRequest, UserRequest,
WaitMode, PreviousMode,
Alertable, Alertable,
UnsafeTime ? &Time : NULL, TimeOut,
WaitBlockArray); WaitBlockArray);
/* dereference all objects */ /* dereference all objects */
for (i = 0; i < Count; i++) for (i = 0; i < ObjectCount; i++)
{ {
ObDereferenceObject(ObjectPtrArray[i]); ObDereferenceObject(ObjectPtrArray[i]);
} }
@ -868,33 +894,47 @@ NtWaitForMultipleObjects(IN ULONG Count,
* @implemented * @implemented
*/ */
NTSTATUS STDCALL NTSTATUS STDCALL
NtWaitForSingleObject(IN HANDLE Object, NtWaitForSingleObject(IN HANDLE ObjectHandle,
IN BOOLEAN Alertable, IN BOOLEAN Alertable,
IN PLARGE_INTEGER UnsafeTime) IN PLARGE_INTEGER TimeOut OPTIONAL)
{ {
PVOID ObjectPtr; PVOID ObjectPtr;
NTSTATUS Status; KPROCESSOR_MODE PreviousMode;
KPROCESSOR_MODE WaitMode; LARGE_INTEGER SafeTimeOut;
LARGE_INTEGER Time; NTSTATUS Status = STATUS_SUCCESS;
DPRINT("NtWaitForSingleObject(Object %x, Alertable %d, Time %x)\n", DPRINT("NtWaitForSingleObject(ObjectHandle %x, Alertable %d, TimeOut %x)\n",
Object,Alertable,Time); ObjectHandle,Alertable,TimeOut);
if (UnsafeTime) PreviousMode = ExGetPreviousMode();
if(TimeOut != NULL && PreviousMode != KernelMode)
{
_SEH_TRY
{ {
Status = MmCopyFromCaller(&Time, UnsafeTime, sizeof(LARGE_INTEGER)); ProbeForRead(TimeOut,
if (!NT_SUCCESS(Status)) sizeof(LARGE_INTEGER),
{ sizeof(ULONG));
return(Status); /* 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(ObjectHandle,
Status = ObReferenceObjectByHandle(Object,
SYNCHRONIZE, SYNCHRONIZE,
NULL, NULL,
WaitMode, PreviousMode,
&ObjectPtr, &ObjectPtr,
NULL); NULL);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
@ -911,9 +951,9 @@ NtWaitForSingleObject(IN HANDLE Object,
{ {
Status = KeWaitForSingleObject(ObjectPtr, Status = KeWaitForSingleObject(ObjectPtr,
UserRequest, UserRequest,
WaitMode, PreviousMode,
Alertable, Alertable,
UnsafeTime ? &Time : NULL); TimeOut);
} }
ObDereferenceObject(ObjectPtr); ObDereferenceObject(ObjectPtr);
@ -923,22 +963,47 @@ NtWaitForSingleObject(IN HANDLE Object,
NTSTATUS STDCALL NTSTATUS STDCALL
NtSignalAndWaitForSingleObject(IN HANDLE SignalObject, NtSignalAndWaitForSingleObject(IN HANDLE ObjectHandleToSignal,
IN HANDLE WaitObject, IN HANDLE WaitableObjectHandle,
IN BOOLEAN Alertable, IN BOOLEAN Alertable,
IN PLARGE_INTEGER Time) IN PLARGE_INTEGER TimeOut OPTIONAL)
{ {
KPROCESSOR_MODE WaitMode; KPROCESSOR_MODE PreviousMode;
DISPATCHER_HEADER* hdr; DISPATCHER_HEADER* hdr;
PVOID SignalObj; PVOID SignalObj;
PVOID WaitObj; PVOID WaitObj;
NTSTATUS Status; LARGE_INTEGER SafeTimeOut;
NTSTATUS Status = STATUS_SUCCESS;
WaitMode = ExGetPreviousMode(); PreviousMode = ExGetPreviousMode();
Status = ObReferenceObjectByHandle(SignalObject,
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, 0,
NULL, NULL,
WaitMode, PreviousMode,
&SignalObj, &SignalObj,
NULL); NULL);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
@ -946,10 +1011,10 @@ NtSignalAndWaitForSingleObject(IN HANDLE SignalObject,
return Status; return Status;
} }
Status = ObReferenceObjectByHandle(WaitObject, Status = ObReferenceObjectByHandle(WaitableObjectHandle,
SYNCHRONIZE, SYNCHRONIZE,
NULL, NULL,
WaitMode, PreviousMode,
&WaitObj, &WaitObj,
NULL); NULL);
if (!NT_SUCCESS(Status)) if (!NT_SUCCESS(Status))
@ -988,9 +1053,9 @@ NtSignalAndWaitForSingleObject(IN HANDLE SignalObject,
Status = KeWaitForSingleObject(WaitObj, Status = KeWaitForSingleObject(WaitObj,
UserRequest, UserRequest,
WaitMode, PreviousMode,
Alertable, Alertable,
Time); TimeOut);
ObDereferenceObject(SignalObj); ObDereferenceObject(SignalObj);
ObDereferenceObject(WaitObj); ObDereferenceObject(WaitObj);

View file

@ -9131,17 +9131,17 @@ NTOSAPI
NTSTATUS NTSTATUS
DDKAPI DDKAPI
NtWaitForSingleObject( NtWaitForSingleObject(
IN HANDLE Object, IN HANDLE ObjectHandle,
IN BOOLEAN Alertable, IN BOOLEAN Alertable,
IN PLARGE_INTEGER Time); IN PLARGE_INTEGER TimeOut OPTIONAL);
NTOSAPI NTOSAPI
NTSTATUS NTSTATUS
DDKAPI DDKAPI
ZwWaitForSingleObject( ZwWaitForSingleObject(
IN HANDLE Object, IN HANDLE ObjectHandle,
IN BOOLEAN Alertable, IN BOOLEAN Alertable,
IN PLARGE_INTEGER Time); IN PLARGE_INTEGER TimeOut OPTIONAL);
NTOSAPI NTOSAPI
NTSTATUS NTSTATUS