Fehler beim Überprüfen von Objekthandles

Einige Treiber müssen Objekte bearbeiten, die von Aufrufenden an sie übergeben werden, oder sie müssen zwei Dateiobjekte gleichzeitig verarbeiten. Beispielsweise kann ein Modemtreiber ein Handle für ein Ereignisobjekt oder ein Netzwerktreiber Handles für zwei verschiedene Dateiobjekte empfangen. Der Treiber muss diese Handles überprüfen. Da sie von einem Aufrufer und nicht über den E/A-Manager übergeben werden, kann der E/A-Manager keine Überprüfungen durchführen.

Im folgenden Codeausschnitt wurde dem Treiber beispielsweise das Handle AscInfo-AddressHandle> übergeben, es wurde jedoch vor dem Aufruf von ObReferenceObjectByHandle nicht überprüft:

   //
   // 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) ) {

Obwohl der Aufruf von ObReferenceObjectByHandle erfolgreich ist, kann der Code nicht sicherstellen, dass der zurückgegebene Zeiger auf ein Dateiobjekt verweist. Es vertraut dem Aufrufer, die richtigen Informationen zu übergeben.

Selbst wenn alle Parameter für den Aufruf von ObReferenceObjectByHandle korrekt sind und der Aufruf erfolgreich ist, kann ein Treiber dennoch unerwartete Ergebnisse erhalten, wenn das Dateiobjekt nicht für seinen Treiber vorgesehen ist. Im folgenden Codefragment geht der Treiber davon aus, dass ein erfolgreicher Aufruf einen Zeiger auf das erwartete Dateiobjekt zurückgibt:

   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 ) 

Obwohl ObReferenceObjectByHandle einen Zeiger auf ein Dateiobjekt zurückgibt, hat der Treiber keine Garantie dafür, dass der Zeiger auf das erwartete Dateiobjekt verweist. In diesem Fall sollte der Treiber den Zeiger überprüfen, bevor er auf die treiberspezifischen Daten unter AcpEndpointFileObject-FsContext> zugreift.

Um solche Probleme zu vermeiden, sollte ein Treiber wie folgt nach gültigen Daten suchen:

  • Überprüfen Sie den Objekttyp, um sicherzustellen, dass er vom Treiber erwartet wird.

  • Stellen Sie sicher, dass der angeforderte Zugriff für den Objekttyp und die erforderlichen Aufgaben geeignet ist. Wenn Ihr Treiber eine schnelle Dateikopie ausführt, stellen Sie für instance sicher, dass das Handle über Lesezugriff verfügt.

  • Stellen Sie sicher, dass Sie den richtigen Zugriffsmodus (UserMode oder KernelMode) angeben und dass der Zugriffsmodus mit dem angeforderten Zugriff kompatibel ist.

  • Wenn der Treiber ein Handle für ein Dateiobjekt erwartet, das der Treiber selbst erstellt hat, überprüfen Sie das Handle mit dem Geräteobjekt oder Treiber. Achten Sie jedoch darauf, filter, die E/A-Anforderungen für seltsame Geräte senden, nicht zu unterbrechen.

  • Wenn Ihr Treiber mehrere Arten von Dateiobjekten unterstützt (z. B. die Steuerkanäle, Adressobjekte und Verbindungen von TDI-Treibern oder Volume-, Verzeichnis- und Dateiobjekten von Dateisystemen), stellen Sie sicher, dass Sie eine Möglichkeit haben, diese zu unterscheiden.