5

ReadFileEx's documentation says:

Accessing the input buffer while a read operation is using the buffer may lead to corruption of the data read into that buffer. Applications must not read from, write to, reallocate, or free the input buffer that a read operation is using until the read operation completes.

This is the first time I've ever heard of reading data causing corruption.
So my question is, why does that happen? How can a read operation possibly cause data corruption?
What's going on underneath that causes this?

Update:

I noticed an interesting sentence on ReadFile's page:

The ReadFile function may fail with ERROR_NOT_ENOUGH_QUOTA, which means the calling process's buffer could not be page-locked.

Maybe this is related to the answer?

4

3 に答える 3

2

よくわからないので、コメントはかなり受け付けていますが、次のように推測します。

ReadFileEx使用するように実装されていますNtReadFile(多かれ少なかれ、それを包む薄いラッパーです)。NtReadFile多くのことを行いますが、 IoBuildAsynchronousFsdRequest(またはIoBuildSynchronousFsdRequest) を使用してそのタスクを実行します。この記事から、次のことがわかります。

ターゲット デバイス オブジェクトがダイレクト i/o (DO_DIRECT_IO) を行うように設定されている場合、IoBuildAsynchronousFsdRequest は MDL を作成してバッファを記述し、ページをロックします

(強調は私です)

MmProbeAndLockPages次に、彼らはで呼び出すと思いますIoWriteAccess。これは、カーネルモードのドライバーによって行われ、ユーザーが提供したバッファー (ユーザーモード) には、読み取りのためにアクセスすることさえできません。

これを行うとどうなるかわかりません。おそらく SEH 例外がスローされ、コードが失敗するでしょう。

編集 編集
された質問で指摘されているように、ReadFile関数でさえ、操作が完了するまでユーザーがバッファから読み取ることを禁止し、返される場合がありますERROR_NOT_ENOUGH_QUOTA:

ReadFile 関数が ERROR_NOT_ENOUGH_QUOTA で失敗する場合があります。これは、呼び出しプロセスのバッファーをページ ロックできなかったことを意味します。

少なくともこれにより、ReadFile(バッファがユーザーによって提供されていない場合) ページが割り当てられ、それがロックされることが明らかになります(私がリンクした記事にも記載されています...)。破損 (ある場合、これについては @David に強く同意します) がユーザー定義バッファでも発生する可能性があるかどうかを理解する必要があります (@Ben が指摘したように、ほとんどの場合、ページのロックは不可能です)。

呼び出しの前に必要なデータ量を知っていて、一度割り当てることができるという理由だけで、ページ フォールトを使用してバッファ オーバーランを検出するとは思わない。

では、なぜデータが破損する可能性があるのでしょうか? 結局のところ、ここにあるものはすべてエラーが原因である可能性がありますが、データの破損が原因ではありません. これは大げさな推測ですが、次のような既知の問題がありましたMmProbeAndLockPages

この問題は、メモリ マネージャーでの競合状態が原因で発生します。ドライバーが MmProbeAndLockPages ルーチンを呼び出すと、このルーチンは別のスレッドによって変更されているデータを読み取ることがあります。したがって、データの破損が発生します。破損したデータの使用方法によっては、アプリケーションまたはシステムがクラッシュする可能性があります。

この問題が非常に低いレベルで解決されているかどうか、またはアプリケーションが何か奇妙なことをした場合にまだ悪用できるかどうかを言うのは難しいです...

于 2013-02-27T16:55:24.920 に答える
1

ほとんどの場合、I/O バッファから読み取るときの破損は、競合状態が原因です。バッファから読み取るときに、バッファが部分的に埋められる可能性があり、バッファが埋められる順序は特定されていません。さらに、Windows は、バッファを所有している間、そこに何かを格納できます。以前のコンテンツまたはファイルからのデータのいずれかが表示される保証はありません。

同じページ内の他のデータにアクセスし続けることは完全に合法であるため、 buffer から読み取るときのアクセス違反とは関係がないことは確かです。使用が禁止されているのは、バッファー自体のみです。ここで、ファイルがバッファなしのダイレクト I/O ( FILE_FLAG_NO_BUFFERING)用に開かれ、ボリューム セクタ サイズがメモリ ページ サイズの倍数である場合、バッファは一連の完全なページに対応する必要があるため、カーネルはより多くのその時点での自由。ただし、これは非常に特殊な条件のセットであり、セクター サイズがメモリ ページ サイズを超えることはめったにありません。

于 2013-02-27T16:59:39.460 に答える
0

2つの文があります。初めに:

読み取り操作がバッファーを使用しているときに入力バッファーにアクセスすると、そのバッファーに読み取られたデータが破損する可能性があります。

に続く:

アプリケーションは、読み取り操作が完了するまで、読み取り操作が使用している入力バッファーの読み取り、書き込み、再割り当て、または解放を行ってはなりません。

ドキュメントには、2 番目の文に記載されている各アクションが最初の文に記載されている破損につながる可能性があることは明示的に記載されていません。次のように述べています。

  1. 読み取り中に入力バッファーにアクセスすると、そのバッファーが破損する可能性があります。
  2. 読み取り中は、バッファーの読み取り、書き込み、再割り当て、または解放を行わないでください。

そのため、ドキュメントを解釈すると、読み取り操作中にバッファーから読み取ると破損する可能性があるとは記載されていません。

于 2013-02-27T17:31:16.267 に答える