With direct I/O, the memory manager builds an MDL that describes the
underlying physical pages that comprise the user data buffer. These pages
are probed for access (i.e. “can the user write to this page?”) and then
locked in memory for the duration of the I/O operation. The user may free on
change the protection on their virtual address, but the underlying physical
pages remain locked in memory. It has to work this way, otherwise we’d be
doomed if we allowed devices to DMA into these addresses.
When you call MmGetSystemAddressForMdlSafe, you map a kernel mode address to
the same set of underlying physical pages as the user data buffer. The user
can invalidate their mapping, but they can’t invalidate yours.
The problem with TOCTOU is that the *content* of the buffer can change, so
you can’t do things like this:
inputStruct = (PMY_STRUCT)MmGetSystemAddressForMdlSafe();
- if (inputStruct->Length <= MAX_TX_LEN) {
- RtlCopyMemory(myBuf, inputStruct->Buffer, inputStruct->Length)
- }
Because the Length field value can change between 1 & 2 above.
All that being said: you can’t encrypt or decrypt directly into the user
data buffer anyway. On write you would scamble the application’s data buffer
(potentially while they are still using it). Read is a bit more subtle, but
the problem there is with the OS use of “dummy pages” to generate large I/Os
to the storage subsystem in order to read fragmented file chunks (this has
been discussed here previously, Google is the best index of the lists)
-scott
OSR
@OSRDrivers
wrote in message news:xxxxx@ntfsd…
Hello,
we are writing a filesystem minifilter to encrypt and decrypt the data which
is going to and coming from the file system. We are intercepting the read
and write IRPs in both pre and post callbacks. And applying
encryption/decryption operations as necessary.
Should we be using direct-IO (rather than buffered-IO) for minifilter
encryption where we encrypt the userland buffer directly? If so, we are
concerned about Time of Check Time of Use vulnerabilities where we use the
function ‘MmGetSystemAddressForMdlSafe’ to get the virtual address from the
MDL in both pre and post callbacks. The risk is that the user process could
have called VirtualFree on the Virtual Address we are trying to encrypt data
at. Please let us know whether we need to take any action to handle the
TOCTOU attack. If the solution is to use
ProbeForRead/ProbeForWrite/Exception Handling, should we be locking the
memory pages in memory?
Another attack we envision is that a userland application could ask us to
encrypt something in a heap managed by ntdll (like Low Fragmentation Heap)
and free and realloc the heap buffer before we start encrypting and we end
up either encrypting a realloced data or heap metadata. This is not as
dangerous though because it would essentially be the userland application
freeing and reallocing the buffer and crashing itself.
Thanks,
S Ramakrishnan