Mini Filter Driver触发Bugcheck D1问题分析
2015-01-04 12:28
218 查看
前段时间帮朋友改进他做的文件加密Mini Filter Driver,好不容易把期待的功能完善好了,测试时开始频繁触发蓝屏,Bugcheck号是D1。WinDbg对这个错误号的简单解释如下:
DRIVER_IRQL_NOT_LESS_OR_EQUAL (d1)
An attempt was made to access a pageable (or completely invalid) address at an interrupt request level (IRQL) that is too high. This is usually caused by drivers using improper addresses.
也就是在高IRQL试图访问可换页内存。看到这种错误的第一反应是头皮发麻。冷静下来后,我回想起以前自己总结出的经验,那就是碰到错误不要慌,首先把错误的所有信息解读清楚。
从栈回溯来看,发生错误的位置如下:
STACK_TEXT:
8078ab6c 99298fff badb0d00 868992b8 89d28620 nt!KiTrap0E+0x1b3
8078ac30 84c587d1 868992b8 8078ac84 9db0cff8 S_Crypt!PostRead+0x27
8078ac60 84c33324 868992b8 0278ac84 9db0cff8 fltmgr!FltvPostOperation+0x71
8078acc8 84c36512 00899258 86899258 10000000 fltmgr!FltpPerformPostCallbacks+0x24a
8078acdc 84c36b46 86899258 8078ad90 8078ad1c fltmgr!FltpProcessIoCompletion+0x10
8078acec 82b50cd4 8a288728 9db08e28 86899258 fltmgr!FltpPassThroughCompletion+0x98
8078ad1c 82896dd3 8a288728 9db08e28 8078ad90 nt!IovpLocalCompletionRoutine+0x14b
8078ad60 82b50b64 00000001 89c09e98 8a234008 nt!IopfCompleteRequest+0x128
8078adc8 85248498 8078adfc 85248abd 8a2336a8 nt!IovCompleteRequest+0x133
这个函数里并没有提升IRQL的相关动作。那为什么会出这个错呢?
因为我之前也没有做Mini Filter Driver的经验,本着认真学习的态度,开始认真阅读WDK的帮助中有关PFLT_POST_OPERATION_CALLBACK的内容。
Post-operation callback routines are called in an arbitrary thread context, at IRQL <= DISPATCH_LEVEL. Because this callback routine can be called at IRQL DISPATCH_LEVEL, it is subject to the following constraints ... ...
大意是说Post-operation回调函数可能在任何线程上下文中被调用,IRQL <= DISPATCH_LEVEL。因为有可能IRQL是DISPATCH_LEVEL,所以会有一些限制。基于当时对WinDbg对D1 bugcheck的解释,我很容易的找到了其中的一个限制,于是认为自己大致明白了这个错误的原因:PostRead函数可能会在DISPATCH_LEVEL被调用,所以在它里面不可以访问paged pool.
Any data structures used in this routine must be allocated from nonpaged pool.
此时,再来看Bugcheck信息里包含的几个参数。
Arguments:
Arg1: 99299000, memory referenced
Arg2: 00000002, IRQL
Arg3: 00000008, value 0 = read operation, 1 = write operation
Arg4: 99298fff, address which referenced memory
惊奇地发现,发出访问请求的地址和被访问的地址都是PostRead函数里的代码地址。这是为什么呢?再冷静下来细看,每次发生蓝屏时,被访问地址的后三位都是000,也就是被访问地址刚好都是一个页的起始地址。猜测是在要执行下一条地址时,下一条地址刚好在另一个内存页上,而这个内存页此时是无效的,所以需要触发Page Fault,而在DISPATCH_LEVEL,这又是不允许的。
再回过头来看WDK的帮助,发现其中还有一条限制如下。之前没有注意到它,可能是因为它太简短,一时没有看明白它的含义。现在明白,它说的是Post-operation回调函数本身不可以是可换页的。
It cannot be made pageable.
经过一番查找,在一个头文件里找到了如下的内容。
修改过后,重新测试,问题消失。
DRIVER_IRQL_NOT_LESS_OR_EQUAL (d1)
An attempt was made to access a pageable (or completely invalid) address at an interrupt request level (IRQL) that is too high. This is usually caused by drivers using improper addresses.
也就是在高IRQL试图访问可换页内存。看到这种错误的第一反应是头皮发麻。冷静下来后,我回想起以前自己总结出的经验,那就是碰到错误不要慌,首先把错误的所有信息解读清楚。
从栈回溯来看,发生错误的位置如下:
STACK_TEXT:
8078ab6c 99298fff badb0d00 868992b8 89d28620 nt!KiTrap0E+0x1b3
8078ac30 84c587d1 868992b8 8078ac84 9db0cff8 S_Crypt!PostRead+0x27
8078ac60 84c33324 868992b8 0278ac84 9db0cff8 fltmgr!FltvPostOperation+0x71
8078acc8 84c36512 00899258 86899258 10000000 fltmgr!FltpPerformPostCallbacks+0x24a
8078acdc 84c36b46 86899258 8078ad90 8078ad1c fltmgr!FltpProcessIoCompletion+0x10
8078acec 82b50cd4 8a288728 9db08e28 86899258 fltmgr!FltpPassThroughCompletion+0x98
8078ad1c 82896dd3 8a288728 9db08e28 8078ad90 nt!IovpLocalCompletionRoutine+0x14b
8078ad60 82b50b64 00000001 89c09e98 8a234008 nt!IopfCompleteRequest+0x128
8078adc8 85248498 8078adfc 85248abd 8a2336a8 nt!IovCompleteRequest+0x133
这个函数里并没有提升IRQL的相关动作。那为什么会出这个错呢?
因为我之前也没有做Mini Filter Driver的经验,本着认真学习的态度,开始认真阅读WDK的帮助中有关PFLT_POST_OPERATION_CALLBACK的内容。
Post-operation callback routines are called in an arbitrary thread context, at IRQL <= DISPATCH_LEVEL. Because this callback routine can be called at IRQL DISPATCH_LEVEL, it is subject to the following constraints ... ...
大意是说Post-operation回调函数可能在任何线程上下文中被调用,IRQL <= DISPATCH_LEVEL。因为有可能IRQL是DISPATCH_LEVEL,所以会有一些限制。基于当时对WinDbg对D1 bugcheck的解释,我很容易的找到了其中的一个限制,于是认为自己大致明白了这个错误的原因:PostRead函数可能会在DISPATCH_LEVEL被调用,所以在它里面不可以访问paged pool.
Any data structures used in this routine must be allocated from nonpaged pool.
此时,再来看Bugcheck信息里包含的几个参数。
Arguments:
Arg1: 99299000, memory referenced
Arg2: 00000002, IRQL
Arg3: 00000008, value 0 = read operation, 1 = write operation
Arg4: 99298fff, address which referenced memory
惊奇地发现,发出访问请求的地址和被访问的地址都是PostRead函数里的代码地址。这是为什么呢?再冷静下来细看,每次发生蓝屏时,被访问地址的后三位都是000,也就是被访问地址刚好都是一个页的起始地址。猜测是在要执行下一条地址时,下一条地址刚好在另一个内存页上,而这个内存页此时是无效的,所以需要触发Page Fault,而在DISPATCH_LEVEL,这又是不允许的。
再回过头来看WDK的帮助,发现其中还有一条限制如下。之前没有注意到它,可能是因为它太简短,一时没有看明白它的含义。现在明白,它说的是Post-operation回调函数本身不可以是可换页的。
It cannot be made pageable.
经过一番查找,在一个头文件里找到了如下的内容。
<pre name="code" class="cpp">#pragma alloc_text(PAGE, S_PostRead)
修改过后,重新测试,问题消失。
#pragma alloc_text(NONPAGED, S_PostRead)再后来,我又追究起为什么刚开始时测试时,没有这样的蓝屏出现,查找之下。原来是在发现功能基本稳定后,打开了Driver Verifier,这大大提高了解发该BSOD的概率。
相关文章推荐
- Managing Contexts in a Minifilter Driver
- Filter Manager and Minifilter Driver Architecture 过滤管理器和微过滤驱动架构
- Visual Studio 2013开发 mini-filter driver step by step (4) - 获取文件名
- Visual Studio 2013开发 mini-filter driver step by step 内核代码段分页alloc_text的使用(9)
- Visual Studio 2013开发 mini-filter driver step by step 应用层与内核通讯(8)
- SetUnhandledExceptionFilter以及Mini-dump文件分析
- (原)docker的一个“Driver aufs failed to remove...”问题的解决和分析
- Visual Studio 2013开发 mini-filter driver step by step (2) - 编译,部署,运行
- Visual Studio 2013开发 mini-filter driver step by step (1) - 创建 mini filter driver 工程
- Visual Studio 2013开发 mini-filter driver step by step (11) driver 签名
- 基于Struts2项目,发布到Websphere服务器时,触发的Filter问题解决
- SetUnhandledExceptionFilter生成Mini-dump文件分析(代码整理)
- SetUnhandledExceptionFilter以及Mini-dump文件分析(转)
- Visual Studio 2013开发 mini-filter driver step by step (3) - 查看运行结果
- Windows中子线程不能触发定时器的问题分析
- Writing a FilterUnloadCallback Routine for a Minifilter Driver 为一个微过滤驱动写一个过滤器卸载回调例程
- 关于spring定时器一次调用却触发了两次trigger的问题分析
- Android中Touch事件分析--解决HorizontalScrollView滑动和按钮事件触发问题
- Visual Studio 2013开发 mini-filter driver step by step 获取文件读写内容(6)
- Cannot find class: ${jdbc.driver}——配置了sqlSessionFactoryBeanName也报错之问题分析