無法檢查緩衝區的大小
處理實作緩衝 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 管理員假設 [ 資訊 ] 欄位中的值有效。 如果呼叫端傳入輸出緩衝區的有效核心模式位址和大小為零位元組,如果驅動程式未檢查輸出緩衝區大小,因而發現錯誤,就會發生嚴重問題。