CVE-2026-93794: smb/client: flush dirty data before punching a hole
In the Linux kernel, the following vulnerability has been resolved:
smb/client: flush dirty data before punching a hole
Punching a hole after a large buffered write may leave the range reported as data. Reproduce it with:
xfsio -f \ -c "pwrite -b 3m -S 0x61 0 3m" \ -c "fpunch 1m 1m" \ -c "seek -h 0" \ -c "seek -d 1m" \ /mnt/test/repro
Punching 1 MiB at offset 1 MiB should produce:
0 1 MiB 2 MiB 3 MiB | DATA | HOLE | DATA | EOF
Instead, the entire file is reported as data. SEEKHOLE(0) returns EOF, and SEEKDATA(1M) returns 1M.
This happens because a dirty folio spanning the punched range can be written back after the punch and refill the hole.
Fix this by flushing and waiting for dirty data in the punched range before invalidating the page cache and issuing FSCTLSETZERODATA.
The xfstests generic/539 pass against Samba/ksmbd with this change.
Affected Software
Remediation
Recommended actions to resolve this vulnerability, in priority order.
- Compensating control
Flush and wait for dirty data in the punched range before invalidating the page cache and issuing FSCTL_SET_ZERO_DATA.
Event History
Frequently Asked Questions
What conditions are needed to trigger the incorrect hole reporting?
The issue occurs when a hole is punched after a large buffered write and a dirty folio spans the range being punched. If that folio is written back after the punch operation, it can refill the intended hole.
How can I determine whether the issue is present?
After writing 3 MiB of buffered data, punch a 1 MiB hole at offset 1 MiB and inspect the file with SEEK_HOLE and SEEK_DATA. An affected system can report the entire file as data, with SEEK_HOLE(0) returning EOF and SEEK_DATA(1 MiB) returning 1 MiB instead of showing a hole from 1 MiB to 2 MiB.
What behavior should be expected after the fix?
The client flushes and waits for dirty data in the punched range before invalidating cached pages and issuing FSCTL_SET_ZERO_DATA. The punched range should then be reported as a hole rather than later being refilled by writeback.