引用用户空间地址时出错
任何驱动程序(无论是支持 IRP 还是快速 I/O 操作)都应在尝试使用之前验证用户空间中的任何地址。 I/O 管理器不会验证此类地址,也不会验证传递到驱动程序的缓冲区中嵌入的指针。
未能验证在 METHOD_NEITHER IOCTL 和 FSCL 中传递的地址
I/O 管理器不对METHOD_NEITHER IOCTL 和 FSCTL 执行任何验证。 若要确保用户空间地址有效,驱动程序必须使用 ProbeForRead 和 ProbeForWrite 例程,将所有缓冲区引用括在 try/除了 块中。
在以下示例中,驱动程序假定 在 Type3InputBuffer 中传递的值表示有效的地址。
case IOCTL_GET_HANDLER:
{
PULONG EntryPoint;
EntryPoint =
IrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
*EntryPoint = (ULONG)DriverEntryPoint;
...
}
以下代码可避免此问题:
case IOCTL_GET_HANDLER:
{
PULONG_PTR EntryPoint;
EntryPoint =
IrpSp->Parameters.DeviceIoControl.Type3InputBuffer;
try
{
if (Irp->RequestorMode != KernelMode)
{
ProbeForWrite(EntryPoint,
sizeof(ULONG_PTR),
TYPE_ALIGNMENT(ULONG_PTR));
}
*EntryPoint = (ULONG_PTR)DriverEntryPoint;
}
except(EXCEPTION_EXECUTE_HANDLER)
{
...
}
...
}
另请注意,正确的代码将 DriverEntryPoint 强制转换为ULONG_PTR,而不是 ULONG。 此更改允许在 64 位 Windows 环境中使用。
无法验证缓冲 I/O 请求中嵌入的指针
通常,驱动程序在缓冲请求中嵌入指针,如以下示例所示:
struct ret_buf
{
void *arg; // Pointer embedded in request
int rval;
};
pBuf = Irp->AssociatedIrp.SystemBuffer;
...
arg = pBuf->arg; // Fetch the embedded pointer
...
// If the arg pointer is not valid, the following
// statement can corrupt the system:
RtlMoveMemory(arg, &info, sizeof(info));
在此示例中,驱动程序应使用 try/except 块中包含的 ProbeXxx 例程来验证嵌入的指针,其方式与前面所述的METHOD_NEITHER IOCTL 相同。 尽管嵌入指针允许驱动程序返回额外信息,但驱动程序可以使用相对偏移量或可变长度缓冲区更高效地实现相同的结果。
有关使用 try/except 块处理无效地址的详细信息,请参阅 处理异常。