I/O 制御コードに関するセキュリティの問題

I/O 制御コードを含む IRP を安全に処理できるかどうかは、IOCTL コードの適切な定義と、ドライバーが IRP で受け取るパラメーターの慎重な調査次第です。

新しい IOCTL コードを定義するときは、次の規則を使用します。

  • 常に、 0x800以上の FunctionCode 値を指定します。

  • 必ず RequiredAccess 値を指定します。 呼び出し元に十分なアクセス権がない場合、I/O マネージャーは IOCTL を送信しません。

  • 呼び出し元にカーネル メモリの非特定領域の読み書きを許可する IOCTL コードは定義しないでください。

ドライバー内で IOCTL コードを処理するときは、次の規則を使用してください。

  • ドライバーのディスパッチ ルーチンが受信した IOCTL コードをテストするときは、必ず 32 ビット値全体をテストする必要があります。

  • IoValidateDeviceIoControlAccess を使用すればドライバーは、I/O コントロール コードの定義で RequiredAccess 値による指定内容よりも厳密なアクセスチェックを動的に実行できます。

  • >Irp-AssociatedIrp.SystemBuffer で指定されたバッファーに格納できるデータ量よりも多くのデータを読み書きしないでください。 そのため、バッファーの制限を決定するには、常に IO_STACK_LOCATION構造体で Parameters.DeviceIoControl.InputBufferLength または Parameters.DeviceIoControl.OutputBufferLength をチェックします。

  • IOCTL 要求の発生元であるアプリケーションを対象としたデータを格納するドライバー割り当てバッファーの値は常に 0 です。 そのため、機密データが誤ってアプリケーションにコピーされることはありません。

  • METHOD_IN_DIRECTとMETHOD_OUT_DIRECT の転送については、上記の規則に従ってください。 さらに、MmGetSystemAddressForMdlSafe からの NULL 戻り値をチェックします。これは、マッピングが失敗したか、長さ 0 のバッファーが指定されたことを示します。

  • METHOD_NEITHER 転送の場合は、「バッファー I/O もダイレクト I/O も使用しない」に記載されている規則に従ってください。