- Check that the operation succeeded prior to copying to the output buffer.
- Avoid information leaks by only copying what is necessary to the output
buffer (suggestion by Tay Kiat Loong).
The WinFsp "transact" protocol is used by user mode file systems to interface
with the FSD. This protocol works via the DeviceIoControl API and uses the
FSP_IOCTL_TRANSACT control code. The FSP_IOCTL_TRANSACT code is marked as
METHOD_BUFFERED.
When the DeviceIoControl call is forwarded as an IRP, the METHOD_BUFFERED flag
instructs the kernel to copy user mode buffers to kernel mode buffers (and
vice-versa). However when the DeviceIoControl call is forwarded via the FastIO
mechanism the METHOD_BUFFERED flag is ignored. This means that when WinFsp
added support for DeviceIoControl FastIO, the FSD started accessing user mode
buffers directly.
This means that a malicious file system could attempt exploits like changing
or freeing a buffer while the FSD is reading it. Tay Kiat Loong developed a
POC exploit which demonstrated this vulnerability.
This commit fixes the problem by patching FspFastIoDeviceControl to add the
missing METHOD_BUFFERED handling.
Some third party filters send us security descriptors in absolute rather
than self-relative format. Handle this case by converting them to self-
relative format ourselves.
Add a check to verify that the TopLevelIrp has not been completed. This
became necessary because on recent Windows kernels, IRP's can have "IRP
extensions", which are freed when an IRP is completed. This can trigger
a recursive CLOSE with a top-level IRP that has been completed, which
can bugcheck the system.
Case in point: the new (Win11) NtCopyFileChunk creates IRP's with
COPY_INFORMATION attached. Upon completion of such an IRP the
SourceFileObject is freed, which results in a recursive IRP_MJ_CLOSE
with a completed top-level IRP, which would lead to a BSOD.