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: Shyam Prasad N <sprasad@microsoft.com>
Reviewed-by: Paulo Alcantara (SUSE) <pc@manguebit.com>
Cc: stable@vger.kernel.org
Fixes: 724244cdb3
("cifs: protect session channel fields with chan_lock")
Signed-off-by: Steve French <stfrench@microsoft.com>
This commit is contained in:
parent
2f0e4f0342
commit
2f4e429c84
@ -1721,7 +1721,7 @@ out_err:
|
||||
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);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user