无法验证对象句柄

某些驱动程序必须操作调用方传递给它们的对象,或者必须同时处理两个文件对象。 例如,调制解调器驱动程序可能会接收事件对象的句柄,或者网络驱动程序可能会接收两个不同的文件对象的句柄。 驱动程序必须验证这些句柄。 由于它们由调用方传递,而不是通过 I/O 管理器,因此 I/O 管理器无法执行任何验证检查。

例如,在以下代码片段中,驱动程序接收了句柄 AscInfo->AddressHandle,但在调用 ObReferenceObjectByHandle 之前尚未验证该句柄:

   //
   // This handle is embedded in a buffered request.
   //
   status = ObReferenceObjectByHandle(
                      AscInfo->AddressHandle,
                      0,
                      NULL,
                      KernelMode,
                      &fileObject,
                      NULL);

   if (NT_SUCCESS(status)) {
       if ( (fileObject->DeviceObject == DeviceObject) &&
            (fileObject->FsContext2 == TRANSPORT_SOCK) ) {

尽管对 ObReferenceObjectByHandle 的调用成功,但代码无法确保返回的指针引用文件对象;它信任调用方传入正确的信息。

即使对 ObReferenceObjectByHandle 的调用的所有参数都正确,并且调用成功,如果文件对象不适合其驱动程序,驱动程序仍会收到意外的结果。 在以下代码片段中,驱动程序假定成功调用将返回指向预期文件对象的指针:

   status = ObReferenceObjectByHandle (
                             AcpInfo->Handle,
                             0L,
                             DesiredAccess,
                             *IoFileObjectType,
                             Irp->RequestorMode,
                             (PVOID *)&AcpEndpointFileObject,
                             NULL);

   if ( !NT_SUCCESS(status) ) {
      goto complete;
   }
   AcpEndpoint = AcpEndpointFileObject->FsContext;

   if ( AcpEndpoint->Type != BlockTypeEndpoint ) 

尽管 ObReferenceObjectByHandle 返回指向文件对象的指针,但驱动程序不能保证指针引用它预期的文件对象。 在这种情况下,驱动程序应在访问 AcpEndpointFileObject-FsContext> 上的特定于驱动程序的数据之前验证指针。

为了避免此类问题,驱动程序应检查有效数据,如下所示:

  • 检查对象类型,确保它符合驱动程序的预期。

  • 确保请求的访问适用于对象类型和所需任务。 例如,如果驱动程序执行快速文件复制,请确保句柄具有读取访问权限。

  • 请确保指定正确的访问模式(UserModeKernelMode),并且访问模式与请求的访问兼容。

  • 如果驱动程序需要驱动程序本身创建的文件对象的句柄,请针对设备对象或驱动程序验证句柄。 但是,请注意不要中断发送奇怪设备的 I/O 请求的筛选器。

  • 如果您的驱动程序支持多种类型的文件对象(例如 TDI 驱动程序的控制通道、地址对象和连接,或文件系统的卷、目录和文件对象),请确保有一种方法来区分它们。