Crash fix
This commit is contained in:
+17
-2
@@ -429,14 +429,29 @@ Return Value:
|
||||
|
||||
if (stack->MajorFunction == IRP_MJ_PNP)
|
||||
{
|
||||
ntStatus = DMF_BusFilter_DispatchPnp(DeviceObject, Irp, stack->MinorFunction);
|
||||
// Capture the minor code BEFORE dispatching. For IRP_MN_REMOVE_DEVICE,
|
||||
// DispatchPnp completes the IRP (invalidating `stack`) and deletes the
|
||||
// device object (invalidating `extension`). Re-reading stack->MinorFunction
|
||||
// afterwards is a use-after-free that can steer us into IoReleaseRemoveLock
|
||||
// on the freed extension.
|
||||
//
|
||||
const UCHAR minorFunction = stack->MinorFunction;
|
||||
|
||||
ntStatus = DMF_BusFilter_DispatchPnp(DeviceObject, Irp, minorFunction);
|
||||
|
||||
// For REMOVE_DEVICE, IoReleaseRemoveLockAndWait inside Relations_RemoveDevice
|
||||
// has already released the lock (and waited for all other holders). A second
|
||||
// release here would corrupt the lock count.
|
||||
//
|
||||
if (stack->MinorFunction != IRP_MN_REMOVE_DEVICE)
|
||||
if (minorFunction != IRP_MN_REMOVE_DEVICE)
|
||||
{
|
||||
// Safe: this is a non-REMOVE minor, so no teardown path ran, and the
|
||||
// IoAcquireRemoveLock reference taken at function entry is still
|
||||
// outstanding here. That outstanding reference blocks any concurrent
|
||||
// IoReleaseRemoveLockAndWait (in Relations_RemoveDevice / DeviceCleanup)
|
||||
// from completing IoDeleteDevice, so `extension` is guaranteed alive at
|
||||
// the moment we release. We must not touch `extension` after this call.
|
||||
//
|
||||
IoReleaseRemoveLock(&extension->RemoveLock, Irp);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user