summaryrefslogtreecommitdiff
path: root/fs
diff options
context:
space:
mode:
authorNamjae Jeon <linkinjeon@kernel.org>2026-07-22 10:04:19 +0900
committerSteve French <stfrench@microsoft.com>2026-07-30 18:45:57 -0500
commite7188199eff46a636f3436356f0aae039be6dd66 (patch)
tree33c2990416671248d4867a207a597295b535d6e6 /fs
parentf5098b6bae761e346ebcd9da7f95622c04733cff (diff)
ksmbd: fix use-after-free in __close_file_table_ids()
A ksmbd_file can remain alive after logical close while another session holds a temporary reference obtained through ksmbd_lookup_fd_inode(). ksmbd_close_fd() currently marks the file closed and drops the idr-owned reference, but leaves the pointer published in the closing session's idr until the final reference is dropped. If the foreign holder performs the final ksmbd_fd_put(), __put_fd_final() supplies the foreign session's file table to __ksmbd_close_fd(). The object is then freed without being removed from its owner's idr, and the owner session later dereferences the stale pointer during file-table teardown. Remove the volatile id from the owner's idr while ksmbd_close_fd() still holds that table's lock, and clear volatile_id before dropping the idr-owned reference. A later foreign final put then only performs physical destruction and cannot remove the object from the wrong table. Fixes: 8510a043d334 ("ksmbd: increment reference count of parent fp") Reported-by: Yunseong Kim <yunseong.kim@est.tech> Signed-off-by: Namjae Jeon <linkinjeon@kernel.org> Signed-off-by: Steve French <stfrench@microsoft.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/smb/server/vfs_cache.c2
1 files changed, 2 insertions, 0 deletions
diff --git a/fs/smb/server/vfs_cache.c b/fs/smb/server/vfs_cache.c
index d95c405eab11..a141025581af 100644
--- a/fs/smb/server/vfs_cache.c
+++ b/fs/smb/server/vfs_cache.c
@@ -697,6 +697,8 @@ int ksmbd_close_fd(struct ksmbd_work *work, u64 id)
fp = NULL;
else {
fp->f_state = FP_CLOSED;
+ idr_remove(ft->idr, id);
+ fp->volatile_id = KSMBD_NO_FID;
closed = true;
if (!atomic_dec_and_test(&fp->refcount))
fp = NULL;