Erreurs lors du référencement d’adresses User-Space

Tout pilote, qu’il s’agisse de prendre en charge des irps ou des opérations d’E/S rapides, doit valider n’importe quelle adresse dans l’espace utilisateur avant d’essayer de l’utiliser. Le gestionnaire d’E/S ne valide pas ces adresses, ni les pointeurs incorporés dans les mémoires tampons passées aux pilotes.

Échec de la validation des adresses passées dans METHOD_NEITHER IOCTL et FSCTL

Le gestionnaire d’E/S n’effectue aucune validation pour METHOD_NEITHER IOCTL et FSCTL. Pour s’assurer que les adresses d’espace utilisateur sont valides, le pilote doit utiliser les routines ProbeForRead et ProbeForWrite , en plaçant toutes les références de mémoire tampon dans des blocs try/except .

Dans l’exemple suivant, le pilote suppose que la valeur passée dans type3InputBuffer représente une adresse valide.

   case IOCTL_GET_HANDLER:
   {
      PULONG EntryPoint;

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

Le code suivant évite ce problème :

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

Notez également que le code correct caste DriverEntryPoint en ULONG_PTR, au lieu d’un ULONG. Cette modification permet une utilisation dans un environnement Windows 64 bits.

Échec de la validation des pointeurs incorporés dans les demandes d’E/S mises en mémoire tampon

Souvent, les pilotes incorporent des pointeurs dans des requêtes mises en mémoire tampon, comme dans l’exemple suivant :

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

Dans cet exemple, le pilote doit valider le pointeur incorporé à l’aide des routines Probe Xxx placées dans un bloc try/except de la même façon que pour les METHOD_NEITHER IOCTL décrites précédemment. Bien que l’incorporation d’un pointeur permette à un pilote de retourner des informations supplémentaires, un pilote peut obtenir plus efficacement le même résultat à l’aide d’un décalage relatif ou d’une mémoire tampon de longueur variable.

Pour plus d’informations sur l’utilisation de blocs try/except pour gérer des adresses non valides, consultez Gestion des exceptions.