Freigeben über


Fehler beim Verweisen auf User-Space-Addressen

Jeder Treiber, unabhängig davon, ob IRPs oder schnelle E/A-Vorgänge unterstützt werden, sollte jede Adresse im Benutzerbereich überprüfen, bevor sie verwendet werden soll. Der E/A-Manager überprüft diese Adressen nicht und überprüft auch keine Zeiger, die in Puffer eingebettet sind, die an Treiber übergeben werden.

Fehler beim Überprüfen von Adressen, die in METHOD_NEITHER IOCTLs und FSCTLs übergeben wurden

Der I/O-Manager führt keinerlei Validierung für METHOD_NEITHER IOCTLs und FSCTLs durch. Um sicherzustellen, dass Benutzerspeicheradressen gültig sind, muss der Treiber die ProbeForRead - und ProbeForWrite-Routinen verwenden, wobei alle Pufferverweise in try/except-Blöcke eingeschlossen werden.

Im folgenden Beispiel geht der Treiber davon aus, dass der im Type3InputBuffer übergebene Wert eine gültige Adresse darstellt.

   case IOCTL_GET_HANDLER:
   {
      PULONG EntryPoint;

      EntryPoint =
         IrpSp->Parameters.DeviceIoControl.Type3InputBuffer; 
      *EntryPoint = (ULONG)DriverEntryPoint; 
      ...
   }

Der folgende Code vermeidet dieses Problem:

   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)
      {
        ...
      }
      ...
   }

Beachten Sie auch, dass der richtige Code DriverEntryPoint in einen ULONG_PTR anstelle eines ULONG konvertiert. Diese Änderung ermöglicht die Verwendung in einer 64-Bit-Windows-Umgebung.

Fehler beim Überprüfen von Zeigern, die in gepufferten E/A-Anforderungen eingebettet sind

Häufig betten Treiber Zeiger in gepufferte Anforderungen ein, wie im folgenden Beispiel gezeigt:

   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));

In diesem Beispiel sollte der Treiber den eingebetteten Zeiger mithilfe der probeXxx-Routinen überprüfen, die in einem try/except-Block auf die gleiche Weise wie für die zuvor beschriebenen METHOD_NEITHER IOCTLs eingeschlossen sind. Obwohl das Einbetten eines Zeigers es einem Treiber ermöglicht, zusätzliche Informationen zurückzugeben, kann ein Treiber dasselbe Ergebnis effizienter erzielen, indem ein relativer Offset oder ein Puffer mit variabler Länge verwendet wird.

Weitere Informationen zum Verwenden von Try/Except-Blöcken zum Behandeln ungültiger Adressen finden Sie unter Behandeln von Ausnahmen.