Partilhar via


Erros na referenciação de endereços User-Space

Qualquer driver, seja suportando IRPs ou operações de E/S rápidas, deve validar qualquer endereço no espaço do usuário antes de tentar usá-lo. O gerenciador de E/S não valida esses endereços, nem valida ponteiros incorporados em buffers passados para drivers.

Falha na validação de endereços passados em IOCTLs e FSCTLs METHOD_NEITHER

O gestor de E/S não realiza qualquer validação para IOCTLs e FSCTLs do tipo METHOD_NEITHER. Para garantir que os endereços de espaço do usuário sejam válidos, o driver deve usar as rotinas ProbeForRead e ProbeForWrite , incluindo todas as referências de buffer em blocos try/except .

No exemplo a seguir, o driver assume que o valor passado no Type3InputBuffer representa um endereço válido.

   case IOCTL_GET_HANDLER:
   {
      PULONG EntryPoint;

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

O código a seguir evita esse 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)
      {
        ...
      }
      ...
   }

Observe também que o código correto converte DriverEntryPoint para um ULONG_PTR, em vez de um ULONG. Essa alteração permite o uso em um ambiente Windows de 64 bits.

Falha na validação de ponteiros incorporados em solicitações de E/S em buffer

Muitas vezes, os drivers incorporam ponteiros em solicitações armazenadas em buffer, como no exemplo a seguir:

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

Neste exemplo, o driver deve validar o ponteiro incorporado usando as rotinas ProbeXxx incluídas em um bloco try/except da mesma forma que para as IOCTLs METHOD_NEITHER descritas anteriormente. Embora a incorporação de um ponteiro permita que um driver retorne informações adicionais, um driver pode alcançar o mesmo resultado de maneira mais eficiente usando um deslocamento relativo ou um buffer de comprimento variável.

Para obter mais informações sobre como usar blocos try/except para manipular endereços inválidos, consulte Manipulando exceções.