summaryrefslogtreecommitdiff
path: root/include/uapi/linux
diff options
context:
space:
mode:
authorFrank Sorenson <sorenson@redhat.com>2026-07-21 18:55:51 -0500
committerSteve French <stfrench@microsoft.com>2026-07-21 20:19:03 -0500
commite8a8d54c2d508891c142a928fc7d298c4c8bd0dd (patch)
treeccef485932aea5821a5cd6b5cb4e8804b5c5d784 /include/uapi/linux
parent2eb74eef4b7eda8df593d22fb48e94ef959ec8a5 (diff)
downloadlinux-e8a8d54c2d508891c142a928fc7d298c4c8bd0dd.tar.gz
linux-e8a8d54c2d508891c142a928fc7d298c4c8bd0dd.zip
cifs: prevent readdir from changing file size due to stale directory metadata
Windows Server's directory enumeration metadata lags behind the actual file size after a write+close or rename. A concurrent readdir() in the window between close() returning to userspace and stat() being called overwrites the correct cached i_size with the stale server value, causing stat() to return the wrong size. Once _cifsFileInfo_put() removes the last writable handle from openFileList, is_size_safe_to_change() permits readdir to overwrite i_size. smb2_close_getattr() then stamps cifs_i->time = jiffies, making the corrupt cached value appear fresh to the next stat(). The existing check (see Fixes:) only blocked stale size updates while an active RW lease was held, not after the last writable handle closes. Add cifsInodeInfo->time_last_write, written via smp_store_release() at writable close and on setattr/truncate. is_size_safe_to_change() checks is_inode_writable() first (acquiring open_file_lock), then rejects a readdir size update if time_last_write falls within acregmax jiffies. The spinlock release in _cifsFileInfo_put() forms a store-release barrier that pairs with the spin_lock() (load-acquire) in is_inode_writable(), ensuring the subsequent smp_load_acquire() on time_last_write observes any update from a concurrent close(). When a size update is rejected and the server value differs from the cached one, cifs_i->time is cleared to force a fresh QUERY_INFO on the next stat(). readdir is also blocked from changing i_size while writable handles are open or an RW lease is held, even on direct-IO mounts. For deferred close (closetimeo > 0), time_last_write is refreshed at the actual server close in smb2_deferred_work_close() and in the cifs_close_deferred_file*() drain paths invoked by lease/oplock breaks and tcon teardown, anchoring the protection window to the real close time rather than the earlier userspace close. time_last_write == 0 skips the time_before() check to avoid false positives near boot on 32-bit systems where jiffies starts close to INITIAL_JIFFIES. Does not reproduce against Samba or with actimeo=0. Fixes: e4b61f3b1c67 ("cifs: prevent updating file size from server if we have a read/write lease") Signed-off-by: Frank Sorenson <sorenson@redhat.com> Signed-off-by: Steve French <stfrench@microsoft.com>
Diffstat (limited to 'include/uapi/linux')
0 files changed, 0 insertions, 0 deletions