登录  | 立即注册

游客您好!登录后享受更多精彩

查看: 31|回复: 1

完成例程跑在 DISPATCH_LEVEL 时,用户缓冲区不能再碰

[复制链接]

13

主题

6

回帖

23

积分

新手上路

积分
23
发表于 昨天 08:24 | 显示全部楼层 |阅读模式
写过滤驱动时,最容易在完成例程里直接碰用户缓冲区。PASSIVE_LEVEL 能碰分页内存,派发到 DISPATCH_LEVEL 之后就不行了,蓝屏码经常是 IRQL_NOT_LESS_OR_EQUAL。

几个我现在固定检查的点:

1. 派发例程开头用 KeGetCurrentIrql 记一笔。如果例程可能被完成例程在 DISPATCH_LEVEL 回调,用户缓冲区必须提前在 PASSIVE_LEVEL 用 MmGetSystemAddressForMdlSafe 映射好,完成例程里只碰这个系统地址。
2. 不要在 DISPATCH_LEVEL 调 ZwXxx、ExAllocatePoolWithTag(PagedPool) 或任何会等待的对象。需要推迟就用 IoQueueWorkItem,回到 PASSIVE_LEVEL 再做。
3. 共享的设备扩展计数用 InterlockedIncrement,不要用普通 ++。自旋锁持有期间不能访问分页内存,锁外再碰用户缓冲。
4. 取消例程和完成例程会并发。IRP 的状态位用 InterlockedExchange 交接,取消例程里 IoReleaseCancelSpinLock 之后不要再假设自己还拥有这个 IRP。

这几条守住之后,注册表缓存、文件过滤这类“完成例程里再写一笔”的代码就不容易在高 IRQL 上踩分页内存。

0

主题

465

回帖

831

积分

高级会员

积分
831
发表于 昨天 20:11 | 显示全部楼层
膜拜神贴,后面的请保持队形~
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|小黑屋|断点社区 |网站地图

GMT+8, 2026-10-3 06:19 , Processed in 0.192037 second(s), 28 queries .

Powered by XiunoBBS

Copyright © 2001-2025, 断点社区.

快速回复 返回顶部 返回列表