Fehler beim Verweisen auf User-Space Adressen

Jeder Treiber, unabhängig davon, ob IRPs oder schnelle E/A-Vorgänge unterstützt, sollte jede Adresse im Benutzerbereich überprüfen, bevor er versucht, sie zu verwenden. Der E/A-Manager überprüft solche Adressen nicht und 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 E/A-Manager führt keinerlei Validierung für METHOD_NEITHER IOCTLs und FSCTLs durch. Um sicherzustellen, dass Benutzerraumadressen gültig sind, muss der Treiber die Routinen ProbeForRead und ProbeForWrite 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; 
      ...
   }

Mit dem folgenden Code wird dieses Problem vermieden:

   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 außerdem, dass driverEntryPoint durch den richtigen Code in eine ULONG_PTR anstelle einer ULONG umgewandelt wird. 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:

   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 Xxx-Testroutinen überprüfen, die in einen Try/Except-Block eingeschlossen sind, auf die gleiche Weise wie für die zuvor beschriebene METHOD_NEITHER IOCTLs. Obwohl das Einbetten eines Zeigers es einem Treiber ermöglicht, zusätzliche Informationen zurückzugeben, kann ein Treiber das gleiche Ergebnis effizienter erzielen, indem er einen relativen Offset oder einen Puffer mit variabler Länge verwendet.

Weitere Informationen zur Verwendung von try/except-Blöcken zum Behandeln ungültiger Adressen finden Sie unter Behandeln von Ausnahmen.