Windows驱动
+ -

驱动中的空地址NULL和MM_BAD_POINTER

2023-02-01 29 0

平时我们对于无效的地址或者不用的地址会将指针初始化为NULL,而NULL会被定义为0

#ifndef NULL
#ifdef __cplusplus
#define NULL    0
#define NULL64  0
#else
#define NULL    ((void *)0)
#define NULL64  ((void * POINTER_64)0)
#endif
#endif // NULL

这对于一般的平台来说,通过NULL来检测内存异常访问是可以的,但不一定所有的硬件平台的驱动都是这样的。

引用一段:

在try/except地址 0 为无效地址的平台上,在 IRQL < DISPATCH_LEVEL 访问地址 0 的驱动程序会导致异常 (访问冲突) 语句可能会无意中捕获该异常。 因此,驱动程序的异常处理代码可能会屏蔽无效访问,并在调试过程中阻止检测这种访问。 但是,可以保证对 MM_BAD_POINTER 地址的访问会导致 bug 检查,异常处理程序无法对此进行屏蔽。

这其实应该说的是代码级的异常接管和驱动级的异常接管。使用NULL的一个弊端应该就是使用try/execep会按管本该由驱动程序的异常接管。这种异常接管应是蓝屏级的。因为在驱动级使用try/except就算接管了异常处理,但由于指针的不正确导致系统驱动级的代码正常运行,这种所谓的运行又是无意义的。并且其并不利于代码BUG的查找与调试。所以使用BSOD使用驱动级的异常是最直接的调试方案。

MM_BAD_POINTER 定义为:

#ifdef _WIN64
#define BAD_POINTER ((PVOID)0xFFFFFFFFFFFFFF00)
#else
#define BAD_POINTER ((PVOID)0xFFFFFF00)
#endif

#define ISPTR(ptr) ((ptr) && ((ptr) != BAD_POINTER))

从代码来看,BAD_POINTER指向的是高端地址,这在代码级是受保护的,并且为所有硬件支台所支持。

其实也会有由于NULL指针未判断而减少一个偏移量导致的驱动级蓝屏。这在我的windows蓝屏生涯中是有遇到的。

下面的代码示例演示如何将 MM_BAD_POINTER 值分配给名为 ptr 的指针变量。 Ntdef.h 标头文件将 PUCHAR 类型定义为指向 unsigned char 的指针。

PUCHAR ptr = (PUCHAR)MM_BAD_POINTER; // Now _ptr is guaranteed to fault._

将 ptr 设置为 MM_BAD_POINTER 后,尝试访问 ptr 指向的内存位置会导致 bug 检查。

事实上,MM_BAD_POINTER 是无效地址的整个页面的基址。 因此,对 MM_BAD_POINTER 至 (MM_BAD_POINTER + PAGE_SIZE - 1) 范围内的地址进行任何访问都会导致 bug 检查。

Windows系统中的PAGE_SIZE均定义为(32、64位):

#define PAGE_SIZE 0x1000

从 Windows 8.1 开始,MM_BAD_POINTER 宏在 Wdm.h 标头文件中定义。 但是,使用此宏定义的驱动程序代码可以在 Windows Vista 及更低版本的 Windows 中运行。

从 Windows Vista 开始,MmBadPointer 全局变量可用作指向某个指针值(保证为无效地址)的指针。 但是,从 Windows 8.1 开始,MmBadPointer 已弃用;应将驱动程序更新为改用 MM_BAD_POINTER 宏。

参考资料:
https://learn.microsoft.com/zh-cn/windows-hardware/drivers/kernel/mm-bad-pointer

0 篇笔记 写笔记

驱动中的空地址NULLMM_BAD_POINTER
平时我们对于无效的地址或者不用的地址会将指针初始化为NULL,而NULL会被定义为0#ifndef NULL#ifdef __cplusplus#define NULL 0#define NULL64 0#else#define NULL ((void *)0)#defi......
BAD_POINTER与NULL
NULL一般被定义为0,但对驱动来说并不是所有的平台中的0地址均无效,因此初始化为NULL的并不一定总能保证可以检测到通过这些指针进行的不当访问。而可以保证 MM_BAD_POINTER 值是运行驱动程序的每个平台上的无效地址。另外,在地址为0的平台上,在 IRQL < DISPATCH_LE......
作者信息
我爱内核
Windows驱动开发,网站开发
好好学习,天天向上。
取消
感谢您的支持,我会继续努力的!
扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

您的支持,是我们前进的动力!