Commit 2f4e429c authored by Shyam Prasad N's avatar Shyam Prasad N Committed by Steve French
Browse files

cifs: lock chan_lock outside match_session



Coverity had rightly indicated a possible deadlock
due to chan_lock being done inside match_session.
All callers of match_* functions should pick up the
necessary locks and call them.

Signed-off-by: default avatarShyam Prasad N <sprasad@microsoft.com>
Reviewed-by: default avatarPaulo Alcantara (SUSE) <pc@manguebit.com>
Cc: stable@vger.kernel.org
Fixes: 724244cd ("cifs: protect session channel fields with chan_lock")
Signed-off-by: default avatarSteve French <stfrench@microsoft.com>
parent 2f0e4f03
Loading
Loading
Loading
Loading
+7 −6
Original line number Diff line number Diff line
@@ -1721,7 +1721,7 @@ cifs_get_tcp_session(struct smb3_fs_context *ctx,
	return ERR_PTR(rc);
}

/* this function must be called with ses_lock held */
/* this function must be called with ses_lock and chan_lock held */
static int match_session(struct cifs_ses *ses, struct smb3_fs_context *ctx)
{
	if (ctx->sectype != Unspecified &&
@@ -1732,12 +1732,8 @@ static int match_session(struct cifs_ses *ses, struct smb3_fs_context *ctx)
	 * If an existing session is limited to less channels than
	 * requested, it should not be reused
	 */
	spin_lock(&ses->chan_lock);
	if (ses->chan_max < ctx->max_channels) {
		spin_unlock(&ses->chan_lock);
	if (ses->chan_max < ctx->max_channels)
		return 0;
	}
	spin_unlock(&ses->chan_lock);

	switch (ses->sectype) {
	case Kerberos:
@@ -1865,10 +1861,13 @@ cifs_find_smb_ses(struct TCP_Server_Info *server, struct smb3_fs_context *ctx)
			spin_unlock(&ses->ses_lock);
			continue;
		}
		spin_lock(&ses->chan_lock);
		if (!match_session(ses, ctx)) {
			spin_unlock(&ses->chan_lock);
			spin_unlock(&ses->ses_lock);
			continue;
		}
		spin_unlock(&ses->chan_lock);
		spin_unlock(&ses->ses_lock);

		++ses->ses_count;
@@ -2693,6 +2692,7 @@ cifs_match_super(struct super_block *sb, void *data)

	spin_lock(&tcp_srv->srv_lock);
	spin_lock(&ses->ses_lock);
	spin_lock(&ses->chan_lock);
	spin_lock(&tcon->tc_lock);
	if (!match_server(tcp_srv, ctx, dfs_super_cmp) ||
	    !match_session(ses, ctx) ||
@@ -2705,6 +2705,7 @@ cifs_match_super(struct super_block *sb, void *data)
	rc = compare_mount_options(sb, mnt_data);
out:
	spin_unlock(&tcon->tc_lock);
	spin_unlock(&ses->chan_lock);
	spin_unlock(&ses->ses_lock);
	spin_unlock(&tcp_srv->srv_lock);