Compartir vía


Errores al hacer referencia a direcciones de User-Space

Cualquier controlador, ya sea compatible con IRP o operaciones de E/S rápidas, debe validar cualquier dirección en el espacio del usuario antes de intentar usarla. El administrador de E/S no valida estas direcciones, ni valida los punteros incrustados en los búferes pasados a los controladores.

Error al validar las direcciones pasadas en METHOD_NEITHER IOCTLs y FSCTLs

El administrador de E/S no realiza ninguna validación para METHOD_NEITHER IOCTLs y FSCTLs. Para asegurarse de que las direcciones de espacio de usuario son válidas, el controlador debe usar las rutinas ProbeForRead y ProbeForWrite , encerrando todas las referencias de búfer en bloques try/except .

En el ejemplo siguiente, el controlador supone que el valor pasado en Type3InputBuffer representa una dirección válida.

   case IOCTL_GET_HANDLER:
   {
      PULONG EntryPoint;

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

El código siguiente evita este problema:

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

Tenga en cuenta también que el código correcto convierte DriverEntryPoint en un ULONG_PTR, en lugar de un ULONG. Este cambio permite su uso en un entorno de Windows de 64 bits.

Error al validar punteros incrustados en solicitudes de E/S almacenadas en búfer

A menudo, los controladores insertan punteros dentro de las solicitudes almacenadas en búfer, como en el ejemplo siguiente:

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

En este ejemplo, el controlador debe validar el puntero incrustado mediante las rutinas Probe Xxx incluidas en un bloque try/except de la misma manera que para los METHOD_NEITHER IOCTLs descritos anteriormente. Aunque la inserción de un puntero permite a un controlador devolver información adicional, un controlador puede lograr el mismo resultado de forma más eficaz mediante un desplazamiento relativo o un búfer de longitud variable.

Para obtener más información sobre el uso de bloques try/except para controlar direcciones no válidas, consulte Control de excepciones.