[NTOS:IO] IopAttachDeviceToDeviceStackSafe(): Attach the device to the device list UNDER lock!

This function is the internal helper for the `IoAttachDevice*()` functions,
in particular for `IoAttachDeviceToDeviceStackSafe()`.

Because the function modifies the chained list of stacked devices, it must
hold the device list lock (the I/O system database lock) while doing the
devices attachment.
In particular, modifying the `SourceDevice`'s extension `AttachedTo` field,
but also modifying its other fields and the `AttachedDevice` ones as well.

This fix is similar to the one already committed in f8cbc3e48c (r70496).

----

In MSDN [^1] it is indicated (although not as clearly as it could be) that
`IoAttachDeviceToDeviceStackSafe()` sets the returned `AttachedToDeviceObject`
pointer under the device list lock. The reason is best spelled in [^2][^3].
Indeed, when a filter attaches to a lower PDO (`PhysicalDevice`) by doing:
```c
myDeviceExtension->LowerDevice =
    IoAttachDeviceToDeviceStack(myFilterDevice, PhysicalDevice);
```
there exists a time window where the function finished attaching the filter
device to the PDO, but hasn't yet returned the device at the top of the
stack to be stored in `myDeviceExtension->LowerDevice` (which gets used
later internally by the filter to pass IRPs down the device stack).
During this time, the filter device may receive some IRPs and its
dispatch routine would use a not-yet initialized `LowerDevice` member.

The IoAttachDeviceToDeviceStackSafe() allows doing:
```c
Status = IoAttachDeviceToDeviceStackSafe(
    myFilterDevice, PhysicalDevice, &myDeviceExtension->LowerDevice);
```
and forbidding the IRPs to be delivered to the filter device, while the
`LowerDevice` member is being initialized with the device list lock held.

----

[^1]: "IoAttachDeviceToDeviceStackSafe function (ntddk.h)"
https://learn.microsoft.com/en-us/windows-hardware/drivers/ddi/ntddk/nf-ntddk-ioattachdevicetodevicestacksafe#remarks

[^2]: "IoAttachDeviceToDeviceStack gotcha" (Satya Das, Winprogger)
https://winprogger.com/ioattachdevicetodevicestack-gotcha/

[^3]: Community OSR answer (by Tony Mason)
https://community.osr.com/t/attach-filter-driver/9450/3
This commit is contained in:
Hermès Bélusca-Maïto
2026-04-07 20:23:54 +02:00
parent 45687e82f3
commit cea19d2e0f
+9 -1
View File
@@ -73,6 +73,10 @@ IopAttachDeviceToDeviceStackSafe(
{
PDEVICE_OBJECT AttachedDevice;
PEXTENDED_DEVOBJ_EXTENSION SourceDeviceExtension;
KIRQL OldIrql;
/* Lock the device list while attaching the device */
OldIrql = KeAcquireQueuedSpinLock(LockQueueIoDatabaseLock);
/* Get the attached device and source extension */
AttachedDevice = IoGetAttachedDevice(TargetDevice);
@@ -107,9 +111,13 @@ IopAttachDeviceToDeviceStackSafe(
SourceDeviceExtension->AttachedTo = AttachedDevice;
}
/* Return the attached device */
/* Return the attached device (under the lock) */
if (AttachedToDeviceObject)
*AttachedToDeviceObject = AttachedDevice;
/* Release the device list lock */
KeReleaseQueuedSpinLock(LockQueueIoDatabaseLock, OldIrql);
return AttachedDevice;
}