Commit 5c76f996 authored by Henrique Carvalho's avatar Henrique Carvalho Committed by Steve French
Browse files

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:
 <TASK>
 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: 4f1fffa2 ("cifs: commands that are retried should have replay flag set")
Reviewed-by: default avatarPaulo Alcantara (Red Hat) <pc@manguebit.com>
Acked-by: default avatarShyam Prasad N <sprasad@microsoft.com>
Reviewed-by: default avatarEnzo Matsumiya <ematsumiya@suse.de>
Signed-off-by: default avatarHenrique Carvalho <henrique.carvalho@suse.com>
Signed-off-by: default avatarSteve French <stfrench@microsoft.com>
parent f765fdfc
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -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);