Ошибки при обращении к адресам User-Space

Любой драйвер, поддерживающий IRP или быстрые операции ввода-вывода, должен проверять любой адрес в пространстве пользователя, прежде чем пытаться использовать его. Диспетчер ввода-вывода не проверяет такие адреса и не проверяет указатели, внедренные в буферы, передаваемые драйверам.

Сбой проверки адресов, переданных в METHOD_NEITHER IOCTLs и FSCTL

Диспетчер ввода-вывода не проверяет METHOD_NEITHER ioCTLs и FSCTLs. Чтобы обеспечить допустимость адресов пользовательского пространства, драйвер должен использовать подпрограммы ProbeForRead и ProbeForWrite , заключив все ссылки на буфер в блоки try/кроме блоков.

В следующем примере драйвер предполагает, что значение, переданное в Type3InputBuffer , представляет допустимый адрес.

   case IOCTL_GET_HANDLER:
   {
      PULONG EntryPoint;

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

Следующий код позволяет избежать этой проблемы:

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

Обратите внимание, что правильный код приводит DriverEntryPoint к ULONG_PTR вместо ULONG. Это изменение позволяет использовать в 64-разрядной среде Windows.

Сбой проверки указателей, внедренных в запросы буферизованного ввода-вывода

Часто драйверы внедряют указатели в буферные запросы, как показано в следующем примере:

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

В этом примере драйвер должен проверить внедренный указатель с помощью процедур пробыXxx , заключенных в блок try/except , так же, как для METHOD_NEITHER IOCTLs, описанных выше. Хотя внедрение указателя позволяет драйверу возвращать дополнительные сведения, драйвер может более эффективно достичь того же результата с помощью относительного смещения или буфера переменной длины.

Дополнительные сведения об использовании блоков try/except для обработки недопустимых адресов см. в разделе Обработка исключений.