Why can premature access to the ReadFileEx input buffer lead to data corruption?

ReadFileEx documentation says:

Accessing the input buffer during a read operation using the buffer can damage data read into this buffer. Applications should not read, write, reallocate, or free up the input buffer that the read operation uses until the read operation completes.

This is the first time I've ever heard of reading data that causes corruption.
So my question is: why is this happening? How can a read operation cause data corruption?
What happens beneath this, what causes it?

Update:

I noticed an interesting suggestion on the ReadFile page :

The ReadFile function may fail using ERROR_NOT_ENOUGH_QUOTA , which means that the buffer of the calling process cannot be blocked on the page.

Perhaps this is due to the answer?

+4
source share
3 answers

I'm not sure, so I'm pretty open to comments, but I think:

ReadFileEx used to use NtReadFile (more or less, it's just a thin wrapper around it). NtReadFile does a lot of things, but uses IoBuildAsynchronousFsdRequest (or IoBuildSynchronousFsdRequest ) to accomplish its task. From this article, we know that:

If the target device object is configured, do direct I / O (DO_DIRECT_IO), then IoBuildAsynchronousFsdRequest creates an MDL to describe the buffer and blocks the pages .

(my emphasis)

Then I assume that they call MmProbeAndLockPages using IoWriteAccess , this is done by the driver in kernel mode, then the buffer available to the user (in user mode) cannot be read.

I don't know what will happen if you do this, the SEH exception will probably be thrown, and your code will fail.

EDIT
As indicated in the edited question, even the ReadFile function prevents the user from reading from the buffer before the operation is completed and can return ERROR_NOT_ENOUGH_QUOTA :

The ReadFile function may fail using ERROR_NOT_ENOUGH_QUOTA, which means that the buffer of the calling process cannot be blocked on the page.

At the very least, it makes it clear that ReadFile (where the buffer is not provided by the user) will select the page and it will block (it’s well said in the article I also contacted ...). It remains to be seen whether corruption (if any, I completely agree with @David) can occur with a user-defined buffer (where blocking on a page, as indicated by @Ben, is impossible in most cases).

I do not think that he uses page errors to detect buffer overflows simply because he knows the required amount of data before the call, and then he can select it once.

So why can the data get corrupted? After all, everything here may be due to an error, but not to data corruption. This is a big guess, but there was a known issue about MmProbeAndLockPages :

This problem occurs due to the race condition in the memory manager. When the driver calls the MmProbeAndLockPages procedure, this procedure can read some data that is being changed by another thread. Consequently, data corruption occurs. Depending on how the damaged data is used, the application or system may crash.

It is hard to say if this problem was resolved at a very low level or if it can still be used if the application does something strange ...

+2
source

Most likely, corruption when you read from the I / O buffer arises from the race condition - the buffer may be partially filled when you read it, and the order in which it is filled is not specified. In addition, Windows can store something there for a time when it owns a buffer - you are not guaranteed the ability to see either previous content or data from a file.

That you can be sure that it is not associated with access violations when reading from the buffer , since it is completely legal to continue accessing other data on the same page. Only your buffer is forbidden to use. Now that the file is open for direct unbuffered I / O ( FILE_FLAG_NO_BUFFERING ), and the sector size of the volume is a multiple of the size of the memory page, then it is necessary that the buffer matches the sequence of full pages, so at this point the kernel has more freedom. But this is a very specific set of conditions, and for the sector size it rarely exceeds the page size of the memory.

+1
source

There are two suggestions. Primarily:

Accessing the input buffer during a read operation using the buffer can damage data read into this buffer.

The following are:

Applications should not read, write, reallocate, or free the input buffer that the read operation uses until the read operation is complete.

The documentation does not explicitly state that each action mentioned in the second sentence can lead to corruption described in the first sentence. It says the following:

  • Accessing the input buffer while reading can damage this buffer and
  • Do not read, write, reallocate, or free the buffer while reading.

So, since I am interpreting the documentation, it does not indicate that reading from the buffer during a read operation can lead to corruption.

0
source

All Articles