Skip to content

Commit bf99f6b

Browse files
Paulo AlcantaraSteve French
authored andcommitted
smb: client: fix missed ses refcounting
Use new cifs_smb_ses_inc_refcount() helper to get an active reference of @SES and @ses->dfs_root_ses (if set). This will prevent @ses->dfs_root_ses of being put in the next call to cifs_put_smb_ses() and thus potentially causing an use-after-free bug. Fixes: 8e35541 ("cifs: fix sharing of DFS connections") Signed-off-by: Paulo Alcantara (SUSE) <pc@manguebit.com> Signed-off-by: Steve French <stfrench@microsoft.com>
1 parent f1f047b commit bf99f6b

File tree

2 files changed

+11
-17
lines changed

2 files changed

+11
-17
lines changed

fs/smb/client/dfs.c

Lines changed: 10 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,12 @@ static int get_session(struct cifs_mount_ctx *mnt_ctx, const char *full_path)
6666
return rc;
6767
}
6868

69+
/*
70+
* Track individual DFS referral servers used by new DFS mount.
71+
*
72+
* On success, their lifetime will be shared by final tcon (dfs_ses_list).
73+
* Otherwise, they will be put by dfs_put_root_smb_sessions() in cifs_mount().
74+
*/
6975
static int add_root_smb_session(struct cifs_mount_ctx *mnt_ctx)
7076
{
7177
struct smb3_fs_context *ctx = mnt_ctx->fs_ctx;
@@ -80,11 +86,12 @@ static int add_root_smb_session(struct cifs_mount_ctx *mnt_ctx)
8086
INIT_LIST_HEAD(&root_ses->list);
8187

8288
spin_lock(&cifs_tcp_ses_lock);
83-
ses->ses_count++;
89+
cifs_smb_ses_inc_refcount(ses);
8490
spin_unlock(&cifs_tcp_ses_lock);
8591
root_ses->ses = ses;
8692
list_add_tail(&root_ses->list, &mnt_ctx->dfs_ses_list);
8793
}
94+
/* Select new DFS referral server so that new referrals go through it */
8895
ctx->dfs_root_ses = ses;
8996
return 0;
9097
}
@@ -242,7 +249,6 @@ static int __dfs_mount_share(struct cifs_mount_ctx *mnt_ctx)
242249
int dfs_mount_share(struct cifs_mount_ctx *mnt_ctx, bool *isdfs)
243250
{
244251
struct smb3_fs_context *ctx = mnt_ctx->fs_ctx;
245-
struct cifs_ses *ses;
246252
bool nodfs = ctx->nodfs;
247253
int rc;
248254

@@ -276,20 +282,8 @@ int dfs_mount_share(struct cifs_mount_ctx *mnt_ctx, bool *isdfs)
276282
}
277283

278284
*isdfs = true;
279-
/*
280-
* Prevent DFS root session of being put in the first call to
281-
* cifs_mount_put_conns(). If another DFS root server was not found
282-
* while chasing the referrals (@ctx->dfs_root_ses == @ses), then we
283-
* can safely put extra refcount of @ses.
284-
*/
285-
ses = mnt_ctx->ses;
286-
mnt_ctx->ses = NULL;
287-
mnt_ctx->server = NULL;
288-
rc = __dfs_mount_share(mnt_ctx);
289-
if (ses == ctx->dfs_root_ses)
290-
cifs_put_smb_ses(ses);
291-
292-
return rc;
285+
add_root_smb_session(mnt_ctx);
286+
return __dfs_mount_share(mnt_ctx);
293287
}
294288

295289
/* Update dfs referral path of superblock */

fs/smb/client/smb2transport.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ smb2_find_smb_ses_unlocked(struct TCP_Server_Info *server, __u64 ses_id)
160160
spin_unlock(&ses->ses_lock);
161161
continue;
162162
}
163-
++ses->ses_count;
163+
cifs_smb_ses_inc_refcount(ses);
164164
spin_unlock(&ses->ses_lock);
165165
return ses;
166166
}

0 commit comments

Comments
 (0)