UsER-MODe dRiVeRs CaN't CraSh THe SYsteM
38ff2bbf-4505-4dbb-851d-fe1e0401f139-image.png
WE LIKE THE STOP 🚀
20210131_110724.jpg
💩 💩 💩
DEBUGGER GO BRRRR
2: kd> !analyze -v
*******************************************************************************
* *
* Bugcheck Analysis *
* *
*******************************************************************************
DRIVER_POWER_STATE_FAILURE (9f)
A driver has failed to complete a power IRP within a specific time.
Arguments:
Arg1: 0000000000000003, A device object has been blocking an Irp for too long a time
Arg2: ffffb68f733afa80, Physical Device Object of the stack
Arg3: fffff500a4e37850, nt!TRIAGE_9F_POWER on Win7 and higher, otherwise the Functional Device Object of the stack
Arg4: ffffb68f73cc0750, The blocked IRP
New day, new challenge 😆
2: kd> !irp ffffb68f73cc0750
...
>[IRP_MJ_POWER(16), IRP_MN_SET_POWER(2)]
0 e1 ffffb68f733afa80 00000000 00000000-00000000 pending
\Driver\BthPS3
Args: 00041100 00000001 00000001 00000002
[IRP_MJ_POWER(16), IRP_MN_SET_POWER(2)]
0 1 ffffb68f72ce6a50 00000000 00000000-00000000 pending
\Driver\WudfRd
Args: 00041100 00000001 00000001 00000002
[IRP_MJ_POWER(16), IRP_MN_SET_POWER(2)]
0 e0 ffffb68f7417d060 00000000 fffff8032f994f90-ffffb68f7417d1b0 Success Error Cancel
\Driver\mshidumdf HIDCLASS!HidpFdoPowerCompletion
Args: 00041100 00000001 00000001 00000002
[IRP_MJ_POWER(16), IRP_MN_SET_POWER(2)]
0 e1 ffffb68f7417d060 00000000 fffff80329365e10-ffffb68f6ec401e8 Success Error Cancel pending
\Driver\mshidumdf nt!PopRequestCompletion
Args: 00041100 00000001 00000001 00000002
[N/A(0), N/A(0)]
0 0 00000000 00000000 00000000-ffffb68f6ec401e8
Args: 00000000 00000000 00000000 00000000
Convenient, two pieces of software written by me who could be the culprits! 🤣
2: kd> !devobj ffffb68f72ce6a50
Device object (ffffb68f72ce6a50) is for:
\Driver\WudfRd DriverObject ffffb68f7135da90
Current Irp 00000000 RefCount 0 Type 0000002a Flags 0000304c
SecurityDescriptor ffff8005098abca0 DevExt ffffb68f72ce6ba0 DevObjExt ffffb68f72ce6bc8
ExtensionFlags (0x00000800) DOE_DEFAULT_SD_PRESENT
Characteristics (0x00000180) FILE_AUTOGENERATED_DEVICE_NAME, FILE_DEVICE_SECURE_OPEN
AttachedDevice (Upper) ffffb68f7417d060 \Driver\mshidumdf
AttachedTo (Lower) ffffb68f733afa80 \Driver\BthPS3
Device queue is not busy.
OK, can't shift the blame, meh. What did I do now... Lets investigate EvtDeviceD0Exit:
NTSTATUS DsHidMini_EvtDeviceD0Exit(
_In_ WDFDEVICE Device,
_In_ WDF_POWER_DEVICE_STATE TargetState
)
{
PDEVICE_CONTEXT pDevCtx;
UNREFERENCED_PARAMETER(TargetState);
FuncEntry(TRACE_POWER);
pDevCtx = DeviceGetContext(Device);
if (pDevCtx->ConnectionType == DsDeviceConnectionTypeUsb)
{
WdfIoTargetStop(WdfUsbTargetPipeGetIoTarget(
pDevCtx->Connection.Usb.InterruptInPipe),
WdfIoTargetCancelSentIo
);
}
if (pDevCtx->ConnectionType == DsDeviceConnectionTypeBth)
{
WdfTimerStop(pDevCtx->Connection.Bth.Timers.HidOutputReport, TRUE);
WdfTimerStop(pDevCtx->Connection.Bth.Timers.HidControlConsume, TRUE);
WdfIoTargetStop(pDevCtx->Connection.Bth.BthIoTarget, WdfIoTargetCancelSentIo);
}
FuncExitNoReturn(TRACE_POWER);
return STATUS_SUCCESS;
}
d48d892a-4b6b-49bc-94be-448f917658fa-image.png
Lets take a closer look to how WdfTimerStop is called...
Wait
[in] KMDF A Boolean value that, if TRUE, specifies that the framework does not return until all queued calls to the driver's deferred procedure calls (DPCs), including the driver's EvtTimerFunc callback functions, have executed.
UMDF A Boolean value that, if TRUE, specifies that the framework does not return until all queued calls to the timer's EvtTimerFunc callback function have executed.
Oh, brilliant idea to block endlessly in the power-down callback 😬 Why endlessly you ask, if I don't do any heavy lifting the timer callback should end within a few milliseconds, right? Well... I start the timer in the callback again, to that it runs periodically 😅 And apparently that is enough to cause a timing issue (no pun intended) that will keep the stop call from completing. Oh well, set it to FALSE, fixed 🎉