禁用MmIsAddressValid

WDK文档明确警告不推荐使用该函数。

MmIsAddressValid例程检测读或写作为参数的虚地址是否会发生缺页。

就算是MmIsAddressValid返回TRUE,访问参数地址仍然可能发生缺页,除非该地址是有效的非分页内存或者锁这块内存.

Syntax

BOOLEAN MmIsAddressValid(
  __in  PVOID VirtualAddress
);

Parameters

VirtualAddress [in]

A pointer to the nonpaged virtual address to check. The caller must ensure that this address cannot be paged out or deleted for the duration of this call. Even after the return from the call, you must not page out or delete this address. If you do page out or delete this address, the return value might be unreliable. Paging out or deleting this address might cause the computer to stop responding (that is,crash).

Return value

If no page fault would occur from reading or writing at the given virtual address, MmIsAddressValid returns TRUE.

一些讨论:

1、对于从User Mode传入的地址,使用ProbeForRead和ProbeForWrite检测。它会确保检测地址是有效的且是用户态的。也可以使用MmProbeAndLockPages

2、NTDEV常见一个问题(包括KMDF小组).  MmIsAddressValid 从名字上看很有用,传入内核虚地址,如果有效则返回TRUE,否则返回FALSE。 似乎是可以用来在使用一个指针前先检测一下它是否有效,正如用户态的APIsIsBadReadPtr and IsBadWritePtr. (在用户态这俩函数should NEVER ever be used. 他们会掩盖错误并且很快会引起corruption)

不幸的是,这个函数完全不是你想的那样。

它真正的功能是:告诉你访问该地址是否会缺页,不是检测它是否有效。MmIsAddressValid仅仅是dereference一下VA, 所以它并不验证地址的有效性 (就像其它内核函数一样).  Windows的有些版本, PagedPool在特定范围的地址区间, 理论上, MmIsAddressvalid可以简单的比较VA参数和PagedPool地址范围, 命中则返回TRUE(this is a drastic simplification, the actual implementation is much more complicated).

如果这个函数真的是检测参数VA是否有效,是否会大有用处?  答案是:否。同样地,IsBadReadPtr等函数也没有太大用处。原因在于时效性,在这个函数返回结果后,另外一个线程可能立刻释放该参数地址。 (as MSDN states for the user mode APIs)

结论: 你需要事先知道你的指针的有效性和正确性。当然在驱动中你必需验证所有使用的用户态地址,但你不可能随机拿来一个内核地址去验证它是否有效。 Like Raymond says, "programming is hard," and you must be 100% in your code or else BSOD the machine.


3、当驱动获得用户态指针  (比如通过METHOD_NEITHER IOCTL或者IOCTL 输入缓冲区的嵌入的指针), 则必需通过Probe函数验证有效性. 通常做法是probe和lock,并且映射到内核模式虚地址. 这样你就可以稍后在这个APP上下文之外使用这些缓冲区. 最后, 如果驱动直接访问用户态地址 (仅限该app上下文!), 驱动要在structured exception block里访问 (如SEH, __try / __except), 来获知无效地址的访问.

4、如果访问无效的内核地址,无论是否有SEH,都会bugcheck。Wrapping each pointer access with SEH will also just suppress the error until some other point in time in the driver (and throw out any chance for the compiler to optimize the code around the SEH block). 

在内核态,关于内核指针,开发者需要知道一个内核指针是否有效。永远别在SEH区块内访问内核地址.



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值