From: Henrique Carvalho Date: Mon, 27 Oct 2025 21:29:19 +0000 (-0300) Subject: smb: client: fix potential cfid UAF in smb2_query_info_compound X-Git-Tag: v6.18-rc4~15^2~2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=5c76f9961c170552c1d07c830b5e145475151600;p=thirdparty%2Fkernel%2Flinux.git smb: client: fix potential cfid UAF in smb2_query_info_compound When smb2_query_info_compound() retries, a previously allocated cfid may have been freed in the first attempt. Because cfid wasn't reset on replay, later cleanup could act on a stale pointer, leading to a potential use-after-free. Reinitialize cfid to NULL under the replay label. Example trace (trimmed): refcount_t: underflow; use-after-free. WARNING: CPU: 1 PID: 11224 at ../lib/refcount.c:28 refcount_warn_saturate+0x9c/0x110 [...] RIP: 0010:refcount_warn_saturate+0x9c/0x110 [...] Call Trace: smb2_query_info_compound+0x29c/0x5c0 [cifs f90b72658819bd21c94769b6a652029a07a7172f] ? step_into+0x10d/0x690 ? __legitimize_path+0x28/0x60 smb2_queryfs+0x6a/0xf0 [cifs f90b72658819bd21c94769b6a652029a07a7172f] smb311_queryfs+0x12d/0x140 [cifs f90b72658819bd21c94769b6a652029a07a7172f] ? kmem_cache_alloc+0x18a/0x340 ? getname_flags+0x46/0x1e0 cifs_statfs+0x9f/0x2b0 [cifs f90b72658819bd21c94769b6a652029a07a7172f] statfs_by_dentry+0x67/0x90 vfs_statfs+0x16/0xd0 user_statfs+0x54/0xa0 __do_sys_statfs+0x20/0x50 do_syscall_64+0x58/0x80 Cc: stable@kernel.org Fixes: 4f1fffa237692 ("cifs: commands that are retried should have replay flag set") Reviewed-by: Paulo Alcantara (Red Hat) Acked-by: Shyam Prasad N Reviewed-by: Enzo Matsumiya Signed-off-by: Henrique Carvalho Signed-off-by: Steve French --- diff --git a/fs/smb/client/smb2ops.c b/fs/smb/client/smb2ops.c index 0f9130ef2e7d6..1e39f2165e427 100644 --- a/fs/smb/client/smb2ops.c +++ b/fs/smb/client/smb2ops.c @@ -2799,11 +2799,12 @@ smb2_query_info_compound(const unsigned int xid, struct cifs_tcon *tcon, struct cifs_fid fid; int rc; __le16 *utf16_path; - struct cached_fid *cfid = NULL; + struct cached_fid *cfid; int retries = 0, cur_sleep = 1; replay_again: /* reinitialize for possible replay */ + cfid = NULL; flags = CIFS_CP_CREATE_CLOSE_OP; oplock = SMB2_OPLOCK_LEVEL_NONE; server = cifs_pick_channel(ses);