Sdílet prostřednictvím


Chyby v odkazování na adresy User-Space

Jakýkoli ovladač, bez ohledu na to, jestli podporuje irps nebo rychlé vstupně-výstupní operace, by měl před pokusem o jeho použití ověřit jakoukoli adresu v uživatelském prostoru. Správce vstupně-výstupních operací tyto adresy neověřuje ani neověřuje ukazatele vložené do vyrovnávacích pamětí předávaných ovladačům.

Selhání ověření adres předaných v METHOD_NEITHER IOCTLs a FSCTLs

Správce vstupně-výstupních operací neprovádí žádné ověřování pro "METHOD_NEITHER" IOCTLs a FSCTLs. Aby bylo zajištěno, že adresy uživatelského prostoru jsou platné, musí ovladač použít rutiny ProbeForRead a ProbeForWrite a ohraničit všechny odkazy na vyrovnávací paměť bloky try/except.

V následujícím příkladu ovladač předpokládá, že hodnota předaná v Type3InputBuffer představuje platnou adresu.

   case IOCTL_GET_HANDLER:
   {
      PULONG EntryPoint;

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

Následující kód se tomuto problému vyhne:

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

Všimněte si také, že správný kód přetypuje DriverEntryPoint na ULONG_PTR místo ULONG. Tato změna umožňuje použití v 64bitovém prostředí Windows.

Nepodařilo se ověřit ukazatele vložené do vstupně-výstupních požadavků ve vyrovnávací paměti

Ovladače často vkládají ukazatele do vyrovnávacích požadavků, což je vidět v následujícím příkladu:

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

V tomto příkladu by ovladač měl ověřit vložený ukazatel pomocí rutin ProbeXxx uzavřených v bloku try/except stejným způsobem jako pro IOCTLs s metodou METHOD_NEITHER popsanou výše. I když vložení ukazatele umožňuje ovladači vrátit další informace, ovladač může efektivněji dosáhnout stejného výsledku pomocí relativního posunu nebo vyrovnávací paměti proměnné délky.

Další informace o použití try/s výjimkou bloků pro zpracování neplatných adres naleznete v tématu Zpracování výjimek.