[NTOSKRNL] In IoGetRelatedDeviceObject(), validate hint is on the stack before return...
[reactos.git] / ntoskrnl / io / iomgr / device.c
index 9342d5a..416a16e 100644 (file)
@@ -5,7 +5,8 @@
  * PURPOSE:         Device Object Management, including Notifications and Queues.
  * PROGRAMMERS:     Alex Ionescu (alex.ionescu@reactos.org)
  *                  Filip Navara (navaraf@reactos.org)
- *                  HervĂ© Poussineau (hpoussin@reactos.org)
+ *                  HervĂ© Poussineau (hpoussin@reactos.org)
+ *                  Pierre Schweitzer
  */
 
 /* INCLUDES *******************************************************************/
@@ -687,6 +688,40 @@ IopGetRelatedTargetDevice(IN PFILE_OBJECT FileObject,
     return Status;
 }
 
+BOOLEAN
+NTAPI
+IopVerifyDeviceObjectOnStack(IN PDEVICE_OBJECT BaseDeviceObject,
+                             IN PDEVICE_OBJECT TopDeviceObjectHint)
+{
+    KIRQL OldIrql;
+    BOOLEAN Result;
+    PDEVICE_OBJECT LoopObject;
+
+    ASSERT(BaseDeviceObject != NULL);
+
+    Result = FALSE;
+    /* Simply loop on the device stack and try to find our hint */
+    OldIrql = KeAcquireQueuedSpinLock(LockQueueIoDatabaseLock);
+    for (LoopObject = BaseDeviceObject; ; LoopObject = LoopObject->AttachedDevice)
+    {
+        /* It was found, it's a success */
+        if (LoopObject == TopDeviceObjectHint)
+        {
+            Result = TRUE;
+            break;
+        }
+
+        /* End of the stack, that's a failure - default */
+        if (LoopObject == NULL)
+        {
+            break;
+        }
+    }
+    KeReleaseQueuedSpinLock(LockQueueIoDatabaseLock, OldIrql);
+
+    return Result;
+}
+
 /* PUBLIC FUNCTIONS ***********************************************************/
 
 /*
@@ -1349,13 +1384,14 @@ IoGetRelatedDeviceObject(IN PFILE_OBJECT FileObject)
             if (FileObject->FileObjectExtension)
             {
                 PFILE_OBJECT_EXTENSION FileObjectExtension;
-                ASSERT(FALSE);
 
                 /* Cast the buffer to something we understand */
                 FileObjectExtension = FileObject->FileObjectExtension;
 
-                /* Check if have a replacement top level device */
-                if (FileObjectExtension->TopDeviceObjectHint)
+                /* Check if have a valid replacement top level device */
+                if (FileObjectExtension->TopDeviceObjectHint &&
+                    IopVerifyDeviceObjectOnStack(DeviceObject,
+                                                 FileObjectExtension->TopDeviceObjectHint))
                 {
                     /* Use this instead of returning the top level device */
                     return FileObjectExtension->TopDeviceObjectHint;