共用方式為


無法檢查緩衝區的大小

處理實作緩衝 I/O 的 IOCTLs 和 FSCTL 時,驅動程式應該一律檢查輸入和輸出緩衝區的大小,以確保緩衝區可以保存所有要求的資料。 如果要求指定FILE_ANY_ACCESS,如同大部分驅動程式 IOCTLs 和 FSCL 一樣,任何具有裝置控制碼的呼叫端都可以存取該裝置的緩衝 IOCTL 或 FSCTL 要求,而且可以在緩衝區結尾之外讀取或寫入資料。

輸入緩衝區大小

例如,假設下列程式碼出現在從 Dispatch 常式呼叫的常式中,而且驅動程式尚未驗證 IRP 中傳遞的緩衝區大小:

   switch (ControlCode)
      ...
      ...
      case IOCTL_NEW_ADDRESS:{
         tNEW_ADDRESS *pNewAddress = 
            pIrp->AssociatedIrp.SystemBuffer;

         pDeviceContext->Addr = RtlUlongByteSwap (pNewAddress->Address);

此範例不會在指派語句 (反白顯示) 之前檢查緩衝區大小。 因此,如果輸入緩衝區不足以包含tNEW_ADDRESS結構,下一行中的 pNewAddress-Address > 參考可能會發生錯誤。

下列程式碼會檢查緩衝區大小,以避免潛在的問題:

   case IOCTL_NEW_ADDRESS: {
      tNEW_ADDRESS *pNewAddress =
         pIrp->AssociatedIrp.SystemBuffer;

      if (pIrpSp->Parameters.DeviceIoControl.InputBufferLength >=
             sizeof(tNEW_ADDRESS)) {
         pDeviceContext->Addr = RtlUlongByteSwap (pNewAddress->Address);

處理其他緩衝 I/O 的程式碼,例如使用可變大小緩衝區的 WMI 要求,可能會有類似的錯誤。

輸出緩衝區大小

輸出緩衝區問題類似于輸入緩衝區問題。 他們可以輕鬆地損毀集區,而且使用者模式呼叫端可能不知道發生任何錯誤。

在下列範例中,驅動程式無法檢查 SystemBuffer的大小:

   case IOCTL_GET_INFO: {

       Info = Irp->AssociatedIrp.SystemBuffer;

       Info->NumIF = NumIF;
       ...
       ...
       Irp->IoStatus.Information =
             NumIF*sizeof(GET_INFO_ITEM)+sizeof(ULONG);
       Irp->IoStatus.Status = ntStatus;
   }

假設系統緩衝區的 NumIF 欄位指定輸入專案的數目,本範例可以將 IoStatus.Information 設定為大於輸出緩衝區的值,因而將太多資訊傳回給使用者模式程式碼。 如果應用程式未正確編碼,而且呼叫的輸出緩衝區太小,則上述程式碼可能會藉由在系統緩衝區結尾以外寫入來損毀集區。

請記住,I/O 管理員假設 [ 資訊 ] 欄位中的值有效。 如果呼叫端傳入輸出緩衝區的有效核心模式位址和大小為零位元組,如果驅動程式未檢查輸出緩衝區大小,因而發現錯誤,就會發生嚴重問題。