diff options
author | Shyam Prasad N <sprasad@microsoft.com> | 2022-07-05 13:16:24 +0200 |
---|---|---|
committer | Steve French <stfrench@microsoft.com> | 2022-07-12 17:35:13 +0200 |
commit | 50bd7d5a647bdf533575111c5335f49707c2ce2f (patch) | |
tree | 6aa819f3e067c1e9fa5b0d59ac91472f9785acf3 /fs/cifs | |
parent | Linux 5.19-rc6 (diff) | |
download | linux-50bd7d5a647bdf533575111c5335f49707c2ce2f.tar.xz linux-50bd7d5a647bdf533575111c5335f49707c2ce2f.zip |
cifs: fix race condition with delayed threads
On failure to create a new channel, first cancel the
delayed threads, which could try to search for this
channel, and not find it.
The other option was to put the tcp session for the
channel first, before decrementing chan_count. But
that would leave a reference to the tcp session, when
it has been freed already.
So going with the former option and cancelling the
delayed works first, before rolling back the channel.
Fixes: aa45dadd34e4 ("cifs: change iface_list from array to sorted linked list")
Signed-off-by: Shyam Prasad N <sprasad@microsoft.com>
Acked-by: Enzo Matsumiya <ematsumiya@suse.de>
Signed-off-by: Steve French <stfrench@microsoft.com>
Diffstat (limited to 'fs/cifs')
-rw-r--r-- | fs/cifs/sess.c | 11 |
1 files changed, 9 insertions, 2 deletions
diff --git a/fs/cifs/sess.c b/fs/cifs/sess.c index b85718f32b53..02c8b2906196 100644 --- a/fs/cifs/sess.c +++ b/fs/cifs/sess.c @@ -474,6 +474,14 @@ cifs_ses_add_channel(struct cifs_sb_info *cifs_sb, struct cifs_ses *ses, out: if (rc && chan->server) { + /* + * we should avoid race with these delayed works before we + * remove this channel + */ + cancel_delayed_work_sync(&chan->server->echo); + cancel_delayed_work_sync(&chan->server->resolve); + cancel_delayed_work_sync(&chan->server->reconnect); + spin_lock(&ses->chan_lock); /* we rely on all bits beyond chan_count to be clear */ cifs_chan_clear_need_reconnect(ses, chan->server); @@ -484,10 +492,9 @@ out: */ WARN_ON(ses->chan_count < 1); spin_unlock(&ses->chan_lock); - } - if (rc && chan->server) cifs_put_tcp_session(chan->server, 0); + } return rc; } |