DiskPerf驱动DiskPerfReadWrite调用KeWaitForSingleObject导致系统蓝屏

一、背景

之前都没什么问题,有一个环境插入某个移动硬盘(后面称"问题U盘")后,系统蓝屏,dump分析结果是

ATTEMPTED_SWITCH_FROM_DPC (b8)
A wait operation, attach process, or yield was attempted from a DPC routine.
This is an illegal operation and the stack track will lead to the offending
code and original DPC routine.
Arguments:
Arg1: 81d156c0, Original thread which is the cause of the failure
Arg2: 90250600, New thread
Arg3: 80e4aca0, Stack address of the original thread
Arg4: 00000000

蓝屏堆栈发生在KeWaitForSingleObject函数

二、修复过程
  1. dump分析结果很明显,不能在DPC例程中调用等待动作的操作,那怎样判断当前例程是否DPC?网上没有找到对应的解决方法
  2. 判断当前例程的IRQL,发现一般U盘的写操作IRQL是PASSIVE_LEVEL(0),插入问题U盘写操作的IRQL是DISPATCH_LEVEL(2)。MSDN显示

Callers of KeWaitForSingleObject must be running at IRQL <= DISPATCH_LEVEL. However, if Timeout = NULL or *Timeout != 0, the caller must be running at IRQL <= APC_LEVEL and in a nonarbitrary thread context. (If Timeout != NULL and *Timeout = 0, the caller must be running at IRQL <= DISPATCH_LEVEL.)

意思是IRQL是DISPATCH_LEVEL(2)的例程中必须满足Timeout != NULL and Timeout = 0这个条件,刚好KeWaitForSingleObject原来timeout是NULL(无限等待),不可以这样子用。于是使用KeGetCurrentIrql来获取当前IRQL,如果是DISPATCH_LEVEL,则把Timeout 设置为 0,调用KeWaitForSingleObject不阻塞,而且返回不是STATUS_TIMEOUT的时候才继续跑。但是这样发现执行了几次写操作后,整个系统卡死了,这里原因也是不很清楚 ,所以这个方法行不通。

然后又把DiskPerf的源码翻出来看了下原来的调用方法,原来调用是没有用事件同步的,看了我们本来的代码,同步也是在下层驱动执行完后,做一些操作如:释放我们申请的Mdl,恢复原来的Mdl,控制返回结果等,这些在完成例程DiskPerfIoCompletion中也可以完成,所以事件同步去掉,后面的操作改到完成函数DiskPerfIoCompletion里面去。但是直接改就出现问题了,IoCallDriver返回STATUS_PENDING给上层后,驱动再也没收到请求,像是卡死了,读写不了。

后来发现是我们的完成函数返回值的问题,因为之前是在KeWaitForSingleObject后完成了irp,现在没同步了,就把外面的IoCompleteRequest去掉了,否则会因为多次完成请求导致蓝屏。这样完成函数就不应该返回STATUS_MORE_PROCESSING_REQUIRED,而要直接返回STATUS_SUCCESS,同时要调用IoMarkIrpPending,修正了完成函数DiskPerfIoCompletion后,功能就正常了

参考:https://www.cnblogs.com/kkindof/articles/3495219.html
https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/wdm/nf-wdm-kewaitforsingleobject
https://docs.microsoft.com/en-us/windows-hardware/drivers/ifs/checking-the-pendingreturned-flag

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值