From: DaeMyung Kang <charsyam@gmail.com>
To: sfrench@samba.org
Cc: pc@manguebit.org, ronniesahlberg@gmail.com,
sprasad@microsoft.com, tom@talpey.com, bharathsm@microsoft.com,
rajasimandal@microsoft.com, linux-cifs@vger.kernel.org,
samba-technical@lists.samba.org, linux-kernel@vger.kernel.org,
DaeMyung Kang <charsyam@gmail.com>
Subject: [PATCH] smb/client: fix chan_max race and rollback in smb3_reconfigure
Date: Thu, 16 Apr 2026 11:28:11 +0900 [thread overview]
Message-ID: <20260416022811.2692096-1-charsyam@gmail.com> (raw)
smb3_reconfigure() has two bugs when handling multichannel remount:
1) smb3_sync_ses_chan_max() is called before acquiring
CIFS_SES_FLAG_SCALE_CHANNELS. If a concurrent operation (e.g.
smb2_reconnect) holds the flag, the current thread takes the
loser path and returns -EINVAL, but ses->chan_max has already
been updated to the new value. This leaves chan_max inconsistent
with the actual channel state.
2) When smb3_update_ses_channels() fails, chan_max is not rolled
back to its previous value and the error is not propagated to
the caller. The mount command returns success even though the
channel configuration was not applied, and repeated failures
cause chan_max to drift further from reality.
Fix both by moving smb3_sync_ses_chan_max() after the
CIFS_SES_FLAG_SCALE_CHANNELS acquisition so the loser path cannot
corrupt chan_max, and by restoring chan_max from old_chan_max on
update failure while still holding the scaling flag to prevent a
concurrent reconfigure from observing the intermediate state.
Propagate the error to the caller so userspace is informed.
Note: smb3_reconfigure() is not fully transactional — credentials
are committed before the multichannel block, so any early return
(including the existing CIFS_SES_FLAG_SCALE_CHANNELS loser path)
can leave ses->password updated while cifs_sb->ctx is not yet
synced. Making the entire function atomic is a larger refactor
and is left for a separate patch.
Tested with a QEMU VM (ksmbd + cifs) using module-parameter-based
fault injection:
- Forced smb3_update_ses_channels() failure via module param and
verified chan_max is preserved at the old value after remount
failure (fault-injection test for rollback).
- Pre-set CIFS_SES_FLAG_SCALE_CHANNELS before entering the
scaling path and verified the loser path returns -EINVAL
without corrupting chan_max (loser-path invariant test).
- Repeated 19 forced-failure remounts with varying max_channels
(range 2-8) and confirmed no chan_max drift (stress test).
All three scenarios pass with the patch and fail without it.
Fixes: ef529f655a2c ("cifs: client: allow changing multichannel mount options on remount")
Signed-off-by: DaeMyung Kang <charsyam@gmail.com>
---
fs/smb/client/fs_context.c | 19 ++++++++++++++++---
1 file changed, 16 insertions(+), 3 deletions(-)
diff --git a/fs/smb/client/fs_context.c b/fs/smb/client/fs_context.c
index b9544eb0381b..99e62c2dbf50 100644
--- a/fs/smb/client/fs_context.c
+++ b/fs/smb/client/fs_context.c
@@ -1085,6 +1085,7 @@ static int smb3_reconfigure(struct fs_context *fc)
struct dentry *root = fc->root;
struct cifs_sb_info *cifs_sb = CIFS_SB(root->d_sb);
struct cifs_ses *ses = cifs_sb_master_tcon(cifs_sb)->ses;
+ unsigned int old_chan_max;
unsigned int rsize = ctx->rsize, wsize = ctx->wsize;
char *new_password = NULL, *new_password2 = NULL;
bool need_recon = false;
@@ -1170,9 +1171,6 @@ static int smb3_reconfigure(struct fs_context *fc)
if ((ctx->multichannel != cifs_sb->ctx->multichannel) ||
(ctx->max_channels != cifs_sb->ctx->max_channels)) {
- /* Synchronize ses->chan_max with the new mount context */
- smb3_sync_ses_chan_max(ses, ctx->max_channels);
- /* Now update the session's channels to match the new configuration */
/* Prevent concurrent scaling operations */
spin_lock(&ses->ses_lock);
if (ses->flags & CIFS_SES_FLAG_SCALE_CHANNELS) {
@@ -1183,16 +1181,31 @@ static int smb3_reconfigure(struct fs_context *fc)
ses->flags |= CIFS_SES_FLAG_SCALE_CHANNELS;
spin_unlock(&ses->ses_lock);
+ old_chan_max = ses->chan_max;
+ /* Synchronize ses->chan_max with the new mount context */
+ smb3_sync_ses_chan_max(ses, ctx->max_channels);
+
mutex_unlock(&ses->session_mutex);
rc = smb3_update_ses_channels(ses, ses->server,
false /* from_reconnect */,
false /* disable_mchan */);
+ /*
+ * On failure, restore chan_max while still holding
+ * CIFS_SES_FLAG_SCALE_CHANNELS so a concurrent reconfigure
+ * cannot observe or race with the rollback.
+ */
+ if (rc < 0)
+ smb3_sync_ses_chan_max(ses, old_chan_max);
+
/* Clear scaling flag after operation */
spin_lock(&ses->ses_lock);
ses->flags &= ~CIFS_SES_FLAG_SCALE_CHANNELS;
spin_unlock(&ses->ses_lock);
+
+ if (rc < 0)
+ return rc;
} else {
mutex_unlock(&ses->session_mutex);
}
--
2.43.0
next reply other threads:[~2026-04-16 2:28 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-04-16 2:28 DaeMyung Kang [this message]
2026-04-16 4:56 ` [PATCH] smb/client: fix chan_max race and rollback in smb3_reconfigure RAJASI MANDAL
2026-04-16 15:18 ` [PATCH v2] smb/client: fix chan_max and UNC state corruption " DaeMyung Kang
2026-04-16 15:48 ` Henrique Carvalho
2026-04-16 20:45 ` [PATCH v3] smb/client: fix state corruption in smb3_reconfigure multichannel path DaeMyung Kang
2026-04-29 3:17 ` RAJASI MANDAL
2026-04-29 12:12 ` CharSyam
2026-04-29 12:10 ` [PATCH v4] smb: client: fix state-consistency bugs in smb3_reconfigure() " DaeMyung Kang
2026-04-29 20:45 ` Henrique Carvalho
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260416022811.2692096-1-charsyam@gmail.com \
--to=charsyam@gmail.com \
--cc=bharathsm@microsoft.com \
--cc=linux-cifs@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=pc@manguebit.org \
--cc=rajasimandal@microsoft.com \
--cc=ronniesahlberg@gmail.com \
--cc=samba-technical@lists.samba.org \
--cc=sfrench@samba.org \
--cc=sprasad@microsoft.com \
--cc=tom@talpey.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox