secured access to buffers in NtWaitForSingleObject(), NtWaitForMultipleObjects()...
authorThomas Bluemel <thomas@reactsoft.com>
Mon, 14 Feb 2005 22:50:15 +0000 (22:50 +0000)
committerThomas Bluemel <thomas@reactsoft.com>
Mon, 14 Feb 2005 22:50:15 +0000 (22:50 +0000)
svn path=/trunk/; revision=13579

reactos/include/ntos/zw.h
reactos/ntoskrnl/ke/wait.c
reactos/w32api/include/ddk/winddk.h

index 5d898bd..37a143d 100755 (executable)
@@ -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
        );
 
 /*
index 8e4da0f..a6575e9 100644 (file)
@@ -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(ObjectCount %lu ObjectsArray[] %x, Alertable %d, "
+         "TimeOut %x)\n", ObjectCount,ObjectsArray,Alertable,TimeOut);
 
-   DPRINT("NtWaitForMultipleObjects(Count %lu Object[] %x, Alertable %d, "
-         "Time %x)\n", Count,Object,Alertable,Time);
+   PreviousMode = ExGetPreviousMode();
 
-   if (Count > MAXIMUM_WAIT_OBJECTS)
+   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);
index 65b707d..a75c0cc 100644 (file)
@@ -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