Bagikan melalui


Kesalahan dalam Mereferensikan Alamat User-Space

Driver apa pun, baik mendukung IRP atau operasi I/O cepat, harus memvalidasi alamat apa pun di ruang pengguna sebelum mencoba menggunakannya. Manajer I/O tidak memvalidasi alamat tersebut, juga tidak memvalidasi pointer yang disematkan dalam buffer yang diteruskan ke driver.

Kegagalan memvalidasi Alamat yang Diteruskan METHOD_NEITHER IOCTL dan FSCTL

Manajer I/O tidak melakukan validasi apa pun untuk IOCTL dan FSCTL METHOD_NEITHER. Untuk memastikan bahwa alamat ruang pengguna valid, driver harus menggunakan rutinitas ProbeForRead dan ProbeForWrite , yang mencakup semua referensi buffer di blok coba/kecuali .

Dalam contoh berikut, driver mengasumsikan bahwa nilai yang diteruskan dalam Type3InputBuffer mewakili alamat yang valid.

   case IOCTL_GET_HANDLER:
   {
      PULONG EntryPoint;

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

Kode berikut menghindari masalah ini:

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

Perhatikan juga bahwa kode yang benar melemparkan DriverEntryPoint ke ULONG_PTR, bukan ULONG. Perubahan ini memungkinkan penggunaan di lingkungan Windows 64-bit.

Kegagalan memvalidasi pointer yang disematkan dalam permintaan I/O yang di-buffer

Seringkali driver menyematkan pointer dalam permintaan buffer, seperti dalam contoh berikut:

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

Dalam contoh ini, driver harus memvalidasi penunjuk yang disematkan dengan menggunakan rutinitas ProbeXxx yang diapit dalam blok coba/kecuali dengan cara yang sama seperti untuk IOCTL METHOD_NEITHER yang dijelaskan sebelumnya. Meskipun menyematkan pointer memungkinkan driver untuk mengembalikan informasi tambahan, driver dapat lebih efisien mencapai hasil yang sama dengan menggunakan offset relatif atau buffer panjang variabel.

Untuk informasi selengkapnya tentang menggunakan blok coba/kecuali untuk menangani alamat yang tidak valid, lihat Menangani Pengecualian.