共用方式為


參考User-Space位址時發生錯誤

無論是支援 IRP 或快速 I/O 作業的任何驅動程式,都應該先驗證使用者空間中的任何位址,然後再嘗試使用它。 I/O 管理員不會驗證這類位址,也不會驗證內嵌在傳遞至驅動程式之緩衝區中的指標。

無法驗證傳入METHOD_NEITHER IOCTLs 和 FSCTL 的位址

I/O 管理員不會驗證METHOD_NEITHER IOCTLs 和 FSCTL。 若要確保使用者空間位址有效,驅動程式必須使用 ProbeForReadProbeForWrite 常式,並將所有緩衝區參考包含在 try/except 區塊中。

在下列範例中,驅動程式假設 在 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 環境中使用。

無法驗證內嵌在緩衝 I/O 要求中的指標

驅動程式通常會在緩衝的要求內嵌指標,如下列範例所示:

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

在此範例中,驅動程式應該使用包含在 try/except區塊中的ProbeXxx常式來驗證內嵌指標,方式與先前所述的METHOD_NEITHER IOCTL 相同。 雖然內嵌指標可讓驅動程式傳回額外的資訊,但驅動程式可以使用相對位移或可變長度緩衝區,更有效率地達到相同的結果。

如需使用 try/except 區塊來處理無效位址的詳細資訊,請參閱 處理例外狀況