WDM驱动RemoveLockForward规则合规问题求助
WDM驱动RemoveLockForward规则校验失败问题排查
接手一个WDM驱动,正尝试使其符合微软标准。运行Static Driver Verifier(SDV)时,发现该驱动未通过RemoveLockForward规则校验。该规则用于验证将IRP转发至其他设备时,IoAcquireRemoveLock与IoReleaseRemoveLock的调用是否合规。
相关源码
Cam_PnpAddDevice函数
NTSTATUS Cam_PnpAddDevice(IN PDRIVER_OBJECT DriverObject, IN PDEVICE_OBJECT PhysicalDeviceObject) { NTSTATUS ntStatus = STATUS_SUCCESS; PDEVICE_OBJECT DeviceObject; PDEVICE_EXTENSION deviceExtension; GUID camGUID; PCAMERA_STATE cameraState; PNODE_DEVICE_EXTENSION pNodeExt; POWER_STATE state; ntStatus = IoCreateDevice(DriverObject, sizeof(DEVICE_EXTENSION), NULL, FILE_DEVICE_UNKNOWN,0, FALSE, &DeviceObject); DeviceObject->Flags |= DO_DIRECT_IO; deviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension; cameraState = &(deviceExtension->CameraState); RtlZeroMemory(deviceExtension, sizeof(DEVICE_EXTENSION)); deviceExtension->CSR_offset = 0xFFFFFFFF; camGUID = GUID_CAMERA; ntStatus = IoRegisterDeviceInterface(PhysicalDeviceObject, &camGUID, NULL, &deviceExtension->SymbolicLinkName); if (!NT_SUCCESS(ntStatus)) { IoDeleteDevice(DeviceObject); ntStatus = STATUS_NO_SUCH_DEVICE; goto Exit_Cam_PnpAddDevice; } deviceExtension->StackDeviceObject = IoAttachDeviceToDeviceStack(DeviceObject, PhysicalDeviceObject); if (!deviceExtension->StackDeviceObject) { // Free up the symbolic link RtlFreeUnicodeString(&deviceExtension->SymbolicLinkName); IoDeleteDevice(DeviceObject); ntStatus = STATUS_NO_SUCH_DEVICE; goto Exit_Cam_PnpAddDevice; } // Save the device object we created as our physical device object deviceExtension->PhysicalDeviceObject = DeviceObject; // Get the port device object pNodeExt = PhysicalDeviceObject->DeviceExtension; deviceExtension->PortDeviceObject = pNodeExt->PortDeviceObject; // Initialize power states deviceExtension->CurrentDevicePowerState.DeviceState = PowerDeviceD0; deviceExtension->CurrentSystemPowerState = PowerSystemWorking; state = deviceExtension->CurrentDevicePowerState; PoSetPowerState(DeviceObject, DevicePowerState, state); // Initialize the spinlock/list to store the bus reset irps... KeInitializeSpinLock(&deviceExtension->ResetSpinLock); KeInitializeSpinLock(&deviceExtension->CromSpinLock); KeInitializeSpinLock(&deviceExtension->AsyncSpinLock); KeInitializeSpinLock(&deviceExtension->IsochSpinLock); KeInitializeSpinLock(&deviceExtension->IsochResourceSpinLock); InitializeListHead(&deviceExtension->BusResetIrps); InitializeListHead(&deviceExtension->CromData); InitializeListHead(&deviceExtension->AsyncAddressData); InitializeListHead(&deviceExtension->IsochDetachData); InitializeListHead(&deviceExtension->IsochResourceData); DeviceObject->Flags &= DO_POWER_PAGABLE; DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING; cameraState->IsochChannel = (ULONG)-1; // Free up the symbolic link RtlFreeUnicodeString(&deviceExtension->SymbolicLinkName); IoInitializeRemoveLock(&deviceExtension->ioRemoveLock, (ULONG)'TCAM', 0, 0); Exit_Cam_PnpAddDevice: return (ntStatus); }
Cam_Pnp函数
NTSTATUS Cam_Pnp(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { NTSTATUS ntStatus = STATUS_SUCCESS; PDEVICE_EXTENSION deviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension; PIO_STACK_LOCATION IrpSp; IrpSp = IoGetCurrentIrpStackLocation(Irp); // This is the line that fails IoAcquireRemoveLock(&deviceExtension->ioRemoveLock, Irp); switch (IrpSp->MinorFunction) { case IRP_MN_STOP_DEVICE: ntStatus = Cam_PnpStopDevice(DeviceObject, Irp); Irp->IoStatus.Status = STATUS_SUCCESS; // Pass down to layer below us... ntStatus = Cam_SubmitIrpAsync(deviceExtension->StackDeviceObject, Irp, NULL); break; } IoReleaseRemoveLock(&deviceExtension->ioRemoveLock, Irp); return (ntStatus); }
SDV输出信息
1: Cam_PnpAddDevice 3: NTSTATUS ntStatus = STATUS_SUCCESS; 11: IoCreateDevice 12: DeviceObject->Flags |= DO_DIRECT_IO; 13: deviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension; 14: cameraState = &(deviceExtension->CameraState); 15: sdv_RtlZeroMemory 16: deviceExtension->CSR_offset = 0xFFFFFFFF; 18: camGUID = GUID_CAMERA; 19: IoRegisterDeviceInterface 20: if (!NT_SUCCESS(ntStatus)) 27: IoAttachDeviceToDeviceStack 28: if (!deviceExtension->StackDeviceObject) 39: deviceExtension->PhysicalDeviceObject = DeviceObject; 42: pNodeExt = PhysicalDeviceObject->DeviceExtension; 43: deviceExtension->PortDeviceObject = pNodeExt->PortDeviceObject; 46: deviceExtension->CurrentDevicePowerState.DeviceState = PowerDeviceD0; 47: deviceExtension->CurrentSystemPowerState = PowerSystemWorking; 49: state = deviceExtension->CurrentDevicePowerState; 50: PoSetPowerState 53: sdv_KeInitializeSpinLock 54: sdv_KeInitializeSpinLock 55: sdv_KeInitializeSpinLock 56: sdv_KeInitializeSpinLock 57: sdv_KeInitializeSpinLock 58: InitializeListHead 59: InitializeListHead 60: InitializeListHead 61: InitializeListHead 62: InitializeListHead 64: DeviceObject->Flags &= DO_POWER_PAGABLE; 65: DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING; 66: cameraState->IsochChannel = (ULONG)-1; 69: RtlFreeUnicodeString 71: sdv_IoInitializeRemoveLock 74: return (ntStatus); ... // There is messages here from the SDV that I did not include because I didn't ... // think they were relevant. If anyone asks I will happily include them. 78: Cam_Pnp 80: NTSTATUS ntStatus = STATUS_SUCCESS; 81: PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension; 84: sdv_IoGetCurrentIrpStackLocation 87: sdv_IoAcquireRemoveLock 9645: switch (choice) 9647: case 0: return STATUS_UNSUCCESSFUL;break; 9659: SLIC_sdv_IoAcquireRemoveLock_exit 82: if(LockDepth > 0 && $return!=STATUS_SUCCESS) 86: else if($return==STATUS_SUCCESS) 9659: Return
问题定位与解决方案
问题根源
在Cam_Pnp函数的IRP_MN_STOP_DEVICE分支中,调用Cam_SubmitIrpAsync将IRP转发至下层设备后,代码仍执行了IoReleaseRemoveLock。RemoveLock的生命周期需与IRP的所有权绑定:当IRP被转发到下层驱动时,当前驱动已不再拥有该IRP的控制权,此时调用IoReleaseRemoveLock属于违规操作——因为RemoveLock是和当前驱动对IRP的处理绑定的,转发后应由下层驱动负责相关的锁操作,或者当前驱动需在转发前确保锁的处理逻辑正确。
另外,当前代码未检查IoAcquireRemoveLock的返回值,如果获取锁失败,后续逻辑仍会执行,这也可能引发问题。
修复方案
处理转发IRP后的锁释放逻辑
对于需要转发的IRP,在调用Cam_SubmitIrpAsync后直接返回,跳过后续的IoReleaseRemoveLock调用,避免对已转交所有权的IRP进行锁操作:case IRP_MN_STOP_DEVICE: ntStatus = Cam_PnpStopDevice(DeviceObject, Irp); Irp->IoStatus.Status = STATUS_SUCCESS; // Pass down to layer below us... ntStatus = Cam_SubmitIrpAsync(deviceExtension->StackDeviceObject, Irp, NULL); // 转发IRP后直接返回,不释放RemoveLock return ntStatus;检查IoAcquireRemoveLock的返回值
在获取RemoveLock后立即检查返回状态,若获取失败则直接完成IRP并返回,避免后续错误逻辑:NTSTATUS acquireStatus = IoAcquireRemoveLock(&deviceExtension->ioRemoveLock, Irp); if (!NT_SUCCESS(acquireStatus)) { Irp->IoStatus.Status = acquireStatus; IoCompleteRequest(Irp, IO_NO_INCREMENT); return acquireStatus; }
内容的提问来源于stack exchange,提问作者Gary
相关产品推荐
相关产品推荐

