fs/smb/client/fs_context.c | 161 +++++++++++++++++++++++++------------ 1 file changed, 108 insertions(+), 53 deletions(-)
smb3_reconfigure() moves strings out of cifs_sb->ctx before the
multichannel update, so a later failure can leave the live context
with NULL strings or options that do not match the session.
Stage the new ctx separately, commit it only on success, and restore
the snapshot on failure. Also make smb3_sync_session_ctx_passwords()
all-or-nothing.
Commit session passwords before channel updates so newly added channels
authenticate with the staged credentials.
Fixes: ef529f655a2c ("cifs: client: allow changing multichannel mount options on remount")
Reported-by: RAJASI MANDAL <rajasimandalos@gmail.com>
Closes: https://lore.kernel.org/lkml/CAEY6_V1+dzW3OD5zqXhsWyXwrDTrg5tAMGZ1AJ7_GAuRE+aevA@mail.gmail.com/
Link: https://lore.kernel.org/lkml/xkr2dlvgibq5j6gkcxd3yhhnj4atgxw2uy4eug2pxm7wy7nbms@iq6cf5taa65v/
Reviewed-by: Henrique Carvalho <henrique.carvalho@suse.com>
Signed-off-by: DaeMyung Kang <charsyam@gmail.com>
---
v6: (feedback from Henrique Carvalho)
- Drop the update_password / update_password2 booleans in
smb3_sync_session_ctx_passwords(); commit when the local pointer
itself is non-NULL.
- Rename the failure label restore_new_ctx -> cleanup_new_ctx, since
new_ctx is cleaned up (not restored) on the staged-failure path.
- Shorten the commit message further per review.
v5: (feedback from Henrique Carvalho)
- Drop mchan_rc / scale_busy; the early failure paths now restore
cifs_sb->ctx from a snapshot taken on entry.
- Build new_ctx separately and replace cifs_sb->ctx only on success.
- Make smb3_sync_session_ctx_passwords() all-or-nothing: allocate
both copies first, commit only when both succeed.
- Switch smb3_sync_ses_chan_max() max_channels parameter to size_t
to match struct cifs_ses::chan_max.
- Shorten the commit message and follow nearby CIFS log style.
fs/smb/client/fs_context.c | 161 +++++++++++++++++++++++++------------
1 file changed, 108 insertions(+), 53 deletions(-)
diff --git a/fs/smb/client/fs_context.c b/fs/smb/client/fs_context.c
index b9544eb0381b..cf6e18876c59 100644
--- a/fs/smb/client/fs_context.c
+++ b/fs/smb/client/fs_context.c
@@ -767,7 +767,7 @@ static int smb3_fs_context_parse_param(struct fs_context *fc,
static int smb3_fs_context_parse_monolithic(struct fs_context *fc,
void *data);
static int smb3_get_tree(struct fs_context *fc);
-static void smb3_sync_ses_chan_max(struct cifs_ses *ses, unsigned int max_channels);
+static void smb3_sync_ses_chan_max(struct cifs_ses *ses, size_t max_channels);
static int smb3_reconfigure(struct fs_context *fc);
static const struct fs_context_operations smb3_fs_context_ops = {
@@ -1041,25 +1041,34 @@ do { \
int smb3_sync_session_ctx_passwords(struct cifs_sb_info *cifs_sb, struct cifs_ses *ses)
{
+ char *password = NULL, *password2 = NULL;
+
if (ses->password &&
cifs_sb->ctx->password &&
strcmp(ses->password, cifs_sb->ctx->password)) {
- kfree_sensitive(cifs_sb->ctx->password);
- cifs_sb->ctx->password = kstrdup(ses->password, GFP_KERNEL);
- if (!cifs_sb->ctx->password)
+ password = kstrdup(ses->password, GFP_KERNEL);
+ if (!password)
return -ENOMEM;
}
if (ses->password2 &&
cifs_sb->ctx->password2 &&
strcmp(ses->password2, cifs_sb->ctx->password2)) {
- kfree_sensitive(cifs_sb->ctx->password2);
- cifs_sb->ctx->password2 = kstrdup(ses->password2, GFP_KERNEL);
- if (!cifs_sb->ctx->password2) {
- kfree_sensitive(cifs_sb->ctx->password);
- cifs_sb->ctx->password = NULL;
+ password2 = kstrdup(ses->password2, GFP_KERNEL);
+ if (!password2) {
+ kfree_sensitive(password);
return -ENOMEM;
}
}
+
+ if (password) {
+ kfree_sensitive(cifs_sb->ctx->password);
+ cifs_sb->ctx->password = password;
+ }
+ if (password2) {
+ kfree_sensitive(cifs_sb->ctx->password2);
+ cifs_sb->ctx->password2 = password2;
+ }
+
return 0;
}
@@ -1072,7 +1081,7 @@ int smb3_sync_session_ctx_passwords(struct cifs_sb_info *cifs_sb, struct cifs_se
* with the session's channel lock. This should be called whenever the maximum
* allowed channels for a session changes (e.g., after a remount or reconfigure).
*/
-static void smb3_sync_ses_chan_max(struct cifs_ses *ses, unsigned int max_channels)
+static void smb3_sync_ses_chan_max(struct cifs_ses *ses, size_t max_channels)
{
spin_lock(&ses->chan_lock);
ses->chan_max = max_channels;
@@ -1082,12 +1091,15 @@ static void smb3_sync_ses_chan_max(struct cifs_ses *ses, unsigned int max_channe
static int smb3_reconfigure(struct fs_context *fc)
{
struct smb3_fs_context *ctx = smb3_fc2context(fc);
+ struct smb3_fs_context *new_ctx = NULL;
+ struct smb3_fs_context *old_ctx = NULL;
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 rsize = ctx->rsize, wsize = ctx->wsize;
char *new_password = NULL, *new_password2 = NULL;
bool need_recon = false;
+ bool need_mchan_update;
int rc;
if (ses->expired_pwd)
@@ -1097,6 +1109,16 @@ static int smb3_reconfigure(struct fs_context *fc)
if (rc)
return rc;
+ old_ctx = kzalloc_obj(*old_ctx);
+ if (!old_ctx)
+ return -ENOMEM;
+
+ rc = smb3_fs_context_dup(old_ctx, cifs_sb->ctx);
+ if (rc) {
+ kfree(old_ctx);
+ return rc;
+ }
+
/*
* We can not change UNC/username/password/domainname/
* workstation_name/nodename/iocharset
@@ -1106,16 +1128,22 @@ static int smb3_reconfigure(struct fs_context *fc)
STEAL_STRING(cifs_sb, ctx, UNC);
STEAL_STRING(cifs_sb, ctx, source);
STEAL_STRING(cifs_sb, ctx, username);
+ STEAL_STRING(cifs_sb, ctx, domainname);
+ STEAL_STRING(cifs_sb, ctx, nodename);
+ STEAL_STRING(cifs_sb, ctx, iocharset);
- if (need_recon == false)
+ if (!need_recon) {
STEAL_STRING_SENSITIVE(cifs_sb, ctx, password);
- else {
+ } else {
if (ctx->password) {
new_password = kstrdup(ctx->password, GFP_KERNEL);
- if (!new_password)
- return -ENOMEM;
- } else
+ if (!new_password) {
+ rc = -ENOMEM;
+ goto restore_ctx;
+ }
+ } else {
STEAL_STRING_SENSITIVE(cifs_sb, ctx, password);
+ }
}
/*
@@ -1125,11 +1153,29 @@ static int smb3_reconfigure(struct fs_context *fc)
if (ctx->password2) {
new_password2 = kstrdup(ctx->password2, GFP_KERNEL);
if (!new_password2) {
- kfree_sensitive(new_password);
- return -ENOMEM;
+ rc = -ENOMEM;
+ goto restore_ctx;
}
- } else
+ } else {
STEAL_STRING_SENSITIVE(cifs_sb, ctx, password2);
+ }
+
+ /* if rsize or wsize not passed in on remount, use previous values */
+ ctx->rsize = rsize ? CIFS_ALIGN_RSIZE(fc, rsize) : cifs_sb->ctx->rsize;
+ ctx->wsize = wsize ? CIFS_ALIGN_WSIZE(fc, wsize) : cifs_sb->ctx->wsize;
+
+ new_ctx = kzalloc_obj(*new_ctx);
+ if (!new_ctx) {
+ rc = -ENOMEM;
+ goto restore_ctx;
+ }
+
+ rc = smb3_fs_context_dup(new_ctx, ctx);
+ if (rc)
+ goto restore_ctx;
+
+ need_mchan_update = ctx->multichannel != cifs_sb->ctx->multichannel ||
+ ctx->max_channels != cifs_sb->ctx->max_channels;
/*
* we may update the passwords in the ses struct below. Make sure we do
@@ -1140,54 +1186,55 @@ static int smb3_reconfigure(struct fs_context *fc)
/*
* smb2_reconnect may swap password and password2 in case session setup
* failed. First get ctx passwords in sync with ses passwords. It should
- * be okay to do this even if this function were to return an error at a
- * later stage
+ * be done before committing new passwords.
*/
rc = smb3_sync_session_ctx_passwords(cifs_sb, ses);
if (rc) {
mutex_unlock(&ses->session_mutex);
- kfree_sensitive(new_password);
- kfree_sensitive(new_password2);
- return rc;
+ goto cleanup_new_ctx;
+ }
+
+ /*
+ * If multichannel or max_channels has changed, update the session's channels accordingly.
+ * This may add or remove channels to match the new configuration.
+ */
+ if (need_mchan_update) {
+ /* Prevent concurrent scaling operations */
+ spin_lock(&ses->ses_lock);
+ if (ses->flags & CIFS_SES_FLAG_SCALE_CHANNELS) {
+ spin_unlock(&ses->ses_lock);
+ mutex_unlock(&ses->session_mutex);
+ rc = -EINVAL;
+ goto cleanup_new_ctx;
+ }
+ ses->flags |= CIFS_SES_FLAG_SCALE_CHANNELS;
+ spin_unlock(&ses->ses_lock);
}
/*
- * now that allocations for passwords are done, commit them
+ * Commit session passwords before any channel work so newly added
+ * channels authenticate with the new credentials.
*/
if (new_password) {
kfree_sensitive(ses->password);
ses->password = new_password;
+ new_password = NULL;
}
if (new_password2) {
kfree_sensitive(ses->password2);
ses->password2 = new_password2;
+ new_password2 = NULL;
}
- /*
- * If multichannel or max_channels has changed, update the session's channels accordingly.
- * This may add or remove channels to match the new configuration.
- */
- if ((ctx->multichannel != cifs_sb->ctx->multichannel) ||
- (ctx->max_channels != cifs_sb->ctx->max_channels)) {
-
+ if (need_mchan_update) {
/* 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) {
- spin_unlock(&ses->ses_lock);
- mutex_unlock(&ses->session_mutex);
- return -EINVAL;
- }
- ses->flags |= CIFS_SES_FLAG_SCALE_CHANNELS;
- spin_unlock(&ses->ses_lock);
mutex_unlock(&ses->session_mutex);
- rc = smb3_update_ses_channels(ses, ses->server,
- false /* from_reconnect */,
- false /* disable_mchan */);
+ smb3_update_ses_channels(ses, ses->server,
+ false /* from_reconnect */,
+ false /* disable_mchan */);
/* Clear scaling flag after operation */
spin_lock(&ses->ses_lock);
@@ -1197,22 +1244,30 @@ static int smb3_reconfigure(struct fs_context *fc)
mutex_unlock(&ses->session_mutex);
}
- STEAL_STRING(cifs_sb, ctx, domainname);
- STEAL_STRING(cifs_sb, ctx, nodename);
- STEAL_STRING(cifs_sb, ctx, iocharset);
-
- /* if rsize or wsize not passed in on remount, use previous values */
- ctx->rsize = rsize ? CIFS_ALIGN_RSIZE(fc, rsize) : cifs_sb->ctx->rsize;
- ctx->wsize = wsize ? CIFS_ALIGN_WSIZE(fc, wsize) : cifs_sb->ctx->wsize;
-
smb3_cleanup_fs_context_contents(cifs_sb->ctx);
- rc = smb3_fs_context_dup(cifs_sb->ctx, ctx);
+ memcpy(cifs_sb->ctx, new_ctx, sizeof(*new_ctx));
+ kfree(new_ctx);
+ new_ctx = NULL;
+ smb3_cleanup_fs_context(old_ctx);
+ old_ctx = NULL;
smb3_update_mnt_flags(cifs_sb);
#ifdef CONFIG_CIFS_DFS_UPCALL
if (!rc)
rc = dfs_cache_remount_fs(cifs_sb);
#endif
+ return rc;
+
+cleanup_new_ctx:
+ smb3_cleanup_fs_context_contents(new_ctx);
+restore_ctx:
+ kfree(new_ctx);
+ kfree_sensitive(new_password);
+ kfree_sensitive(new_password2);
+ smb3_cleanup_fs_context_contents(cifs_sb->ctx);
+ memcpy(cifs_sb->ctx, old_ctx, sizeof(*old_ctx));
+ kfree(old_ctx);
+
return rc;
}
--
2.43.0
Merged into cifs-2.6.git for-next pending additional testing, but
Rajasi will need to update some of her remount series due to this
patch (e.g. "smb: client: sync tcon-level options on remount")
On Wed, May 13, 2026 at 8:54 AM DaeMyung Kang <charsyam@gmail.com> wrote:
>
> smb3_reconfigure() moves strings out of cifs_sb->ctx before the
> multichannel update, so a later failure can leave the live context
> with NULL strings or options that do not match the session.
>
> Stage the new ctx separately, commit it only on success, and restore
> the snapshot on failure. Also make smb3_sync_session_ctx_passwords()
> all-or-nothing.
>
> Commit session passwords before channel updates so newly added channels
> authenticate with the staged credentials.
>
> Fixes: ef529f655a2c ("cifs: client: allow changing multichannel mount options on remount")
> Reported-by: RAJASI MANDAL <rajasimandalos@gmail.com>
> Closes: https://lore.kernel.org/lkml/CAEY6_V1+dzW3OD5zqXhsWyXwrDTrg5tAMGZ1AJ7_GAuRE+aevA@mail.gmail.com/
> Link: https://lore.kernel.org/lkml/xkr2dlvgibq5j6gkcxd3yhhnj4atgxw2uy4eug2pxm7wy7nbms@iq6cf5taa65v/
> Reviewed-by: Henrique Carvalho <henrique.carvalho@suse.com>
> Signed-off-by: DaeMyung Kang <charsyam@gmail.com>
> ---
> v6: (feedback from Henrique Carvalho)
> - Drop the update_password / update_password2 booleans in
> smb3_sync_session_ctx_passwords(); commit when the local pointer
> itself is non-NULL.
> - Rename the failure label restore_new_ctx -> cleanup_new_ctx, since
> new_ctx is cleaned up (not restored) on the staged-failure path.
> - Shorten the commit message further per review.
>
> v5: (feedback from Henrique Carvalho)
> - Drop mchan_rc / scale_busy; the early failure paths now restore
> cifs_sb->ctx from a snapshot taken on entry.
> - Build new_ctx separately and replace cifs_sb->ctx only on success.
> - Make smb3_sync_session_ctx_passwords() all-or-nothing: allocate
> both copies first, commit only when both succeed.
> - Switch smb3_sync_ses_chan_max() max_channels parameter to size_t
> to match struct cifs_ses::chan_max.
> - Shorten the commit message and follow nearby CIFS log style.
>
> fs/smb/client/fs_context.c | 161 +++++++++++++++++++++++++------------
> 1 file changed, 108 insertions(+), 53 deletions(-)
>
> diff --git a/fs/smb/client/fs_context.c b/fs/smb/client/fs_context.c
> index b9544eb0381b..cf6e18876c59 100644
> --- a/fs/smb/client/fs_context.c
> +++ b/fs/smb/client/fs_context.c
> @@ -767,7 +767,7 @@ static int smb3_fs_context_parse_param(struct fs_context *fc,
> static int smb3_fs_context_parse_monolithic(struct fs_context *fc,
> void *data);
> static int smb3_get_tree(struct fs_context *fc);
> -static void smb3_sync_ses_chan_max(struct cifs_ses *ses, unsigned int max_channels);
> +static void smb3_sync_ses_chan_max(struct cifs_ses *ses, size_t max_channels);
> static int smb3_reconfigure(struct fs_context *fc);
>
> static const struct fs_context_operations smb3_fs_context_ops = {
> @@ -1041,25 +1041,34 @@ do { \
>
> int smb3_sync_session_ctx_passwords(struct cifs_sb_info *cifs_sb, struct cifs_ses *ses)
> {
> + char *password = NULL, *password2 = NULL;
> +
> if (ses->password &&
> cifs_sb->ctx->password &&
> strcmp(ses->password, cifs_sb->ctx->password)) {
> - kfree_sensitive(cifs_sb->ctx->password);
> - cifs_sb->ctx->password = kstrdup(ses->password, GFP_KERNEL);
> - if (!cifs_sb->ctx->password)
> + password = kstrdup(ses->password, GFP_KERNEL);
> + if (!password)
> return -ENOMEM;
> }
> if (ses->password2 &&
> cifs_sb->ctx->password2 &&
> strcmp(ses->password2, cifs_sb->ctx->password2)) {
> - kfree_sensitive(cifs_sb->ctx->password2);
> - cifs_sb->ctx->password2 = kstrdup(ses->password2, GFP_KERNEL);
> - if (!cifs_sb->ctx->password2) {
> - kfree_sensitive(cifs_sb->ctx->password);
> - cifs_sb->ctx->password = NULL;
> + password2 = kstrdup(ses->password2, GFP_KERNEL);
> + if (!password2) {
> + kfree_sensitive(password);
> return -ENOMEM;
> }
> }
> +
> + if (password) {
> + kfree_sensitive(cifs_sb->ctx->password);
> + cifs_sb->ctx->password = password;
> + }
> + if (password2) {
> + kfree_sensitive(cifs_sb->ctx->password2);
> + cifs_sb->ctx->password2 = password2;
> + }
> +
> return 0;
> }
>
> @@ -1072,7 +1081,7 @@ int smb3_sync_session_ctx_passwords(struct cifs_sb_info *cifs_sb, struct cifs_se
> * with the session's channel lock. This should be called whenever the maximum
> * allowed channels for a session changes (e.g., after a remount or reconfigure).
> */
> -static void smb3_sync_ses_chan_max(struct cifs_ses *ses, unsigned int max_channels)
> +static void smb3_sync_ses_chan_max(struct cifs_ses *ses, size_t max_channels)
> {
> spin_lock(&ses->chan_lock);
> ses->chan_max = max_channels;
> @@ -1082,12 +1091,15 @@ static void smb3_sync_ses_chan_max(struct cifs_ses *ses, unsigned int max_channe
> static int smb3_reconfigure(struct fs_context *fc)
> {
> struct smb3_fs_context *ctx = smb3_fc2context(fc);
> + struct smb3_fs_context *new_ctx = NULL;
> + struct smb3_fs_context *old_ctx = NULL;
> 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 rsize = ctx->rsize, wsize = ctx->wsize;
> char *new_password = NULL, *new_password2 = NULL;
> bool need_recon = false;
> + bool need_mchan_update;
> int rc;
>
> if (ses->expired_pwd)
> @@ -1097,6 +1109,16 @@ static int smb3_reconfigure(struct fs_context *fc)
> if (rc)
> return rc;
>
> + old_ctx = kzalloc_obj(*old_ctx);
> + if (!old_ctx)
> + return -ENOMEM;
> +
> + rc = smb3_fs_context_dup(old_ctx, cifs_sb->ctx);
> + if (rc) {
> + kfree(old_ctx);
> + return rc;
> + }
> +
> /*
> * We can not change UNC/username/password/domainname/
> * workstation_name/nodename/iocharset
> @@ -1106,16 +1128,22 @@ static int smb3_reconfigure(struct fs_context *fc)
> STEAL_STRING(cifs_sb, ctx, UNC);
> STEAL_STRING(cifs_sb, ctx, source);
> STEAL_STRING(cifs_sb, ctx, username);
> + STEAL_STRING(cifs_sb, ctx, domainname);
> + STEAL_STRING(cifs_sb, ctx, nodename);
> + STEAL_STRING(cifs_sb, ctx, iocharset);
>
> - if (need_recon == false)
> + if (!need_recon) {
> STEAL_STRING_SENSITIVE(cifs_sb, ctx, password);
> - else {
> + } else {
> if (ctx->password) {
> new_password = kstrdup(ctx->password, GFP_KERNEL);
> - if (!new_password)
> - return -ENOMEM;
> - } else
> + if (!new_password) {
> + rc = -ENOMEM;
> + goto restore_ctx;
> + }
> + } else {
> STEAL_STRING_SENSITIVE(cifs_sb, ctx, password);
> + }
> }
>
> /*
> @@ -1125,11 +1153,29 @@ static int smb3_reconfigure(struct fs_context *fc)
> if (ctx->password2) {
> new_password2 = kstrdup(ctx->password2, GFP_KERNEL);
> if (!new_password2) {
> - kfree_sensitive(new_password);
> - return -ENOMEM;
> + rc = -ENOMEM;
> + goto restore_ctx;
> }
> - } else
> + } else {
> STEAL_STRING_SENSITIVE(cifs_sb, ctx, password2);
> + }
> +
> + /* if rsize or wsize not passed in on remount, use previous values */
> + ctx->rsize = rsize ? CIFS_ALIGN_RSIZE(fc, rsize) : cifs_sb->ctx->rsize;
> + ctx->wsize = wsize ? CIFS_ALIGN_WSIZE(fc, wsize) : cifs_sb->ctx->wsize;
> +
> + new_ctx = kzalloc_obj(*new_ctx);
> + if (!new_ctx) {
> + rc = -ENOMEM;
> + goto restore_ctx;
> + }
> +
> + rc = smb3_fs_context_dup(new_ctx, ctx);
> + if (rc)
> + goto restore_ctx;
> +
> + need_mchan_update = ctx->multichannel != cifs_sb->ctx->multichannel ||
> + ctx->max_channels != cifs_sb->ctx->max_channels;
>
> /*
> * we may update the passwords in the ses struct below. Make sure we do
> @@ -1140,54 +1186,55 @@ static int smb3_reconfigure(struct fs_context *fc)
> /*
> * smb2_reconnect may swap password and password2 in case session setup
> * failed. First get ctx passwords in sync with ses passwords. It should
> - * be okay to do this even if this function were to return an error at a
> - * later stage
> + * be done before committing new passwords.
> */
> rc = smb3_sync_session_ctx_passwords(cifs_sb, ses);
> if (rc) {
> mutex_unlock(&ses->session_mutex);
> - kfree_sensitive(new_password);
> - kfree_sensitive(new_password2);
> - return rc;
> + goto cleanup_new_ctx;
> + }
> +
> + /*
> + * If multichannel or max_channels has changed, update the session's channels accordingly.
> + * This may add or remove channels to match the new configuration.
> + */
> + if (need_mchan_update) {
> + /* Prevent concurrent scaling operations */
> + spin_lock(&ses->ses_lock);
> + if (ses->flags & CIFS_SES_FLAG_SCALE_CHANNELS) {
> + spin_unlock(&ses->ses_lock);
> + mutex_unlock(&ses->session_mutex);
> + rc = -EINVAL;
> + goto cleanup_new_ctx;
> + }
> + ses->flags |= CIFS_SES_FLAG_SCALE_CHANNELS;
> + spin_unlock(&ses->ses_lock);
> }
>
> /*
> - * now that allocations for passwords are done, commit them
> + * Commit session passwords before any channel work so newly added
> + * channels authenticate with the new credentials.
> */
> if (new_password) {
> kfree_sensitive(ses->password);
> ses->password = new_password;
> + new_password = NULL;
> }
> if (new_password2) {
> kfree_sensitive(ses->password2);
> ses->password2 = new_password2;
> + new_password2 = NULL;
> }
>
> - /*
> - * If multichannel or max_channels has changed, update the session's channels accordingly.
> - * This may add or remove channels to match the new configuration.
> - */
> - if ((ctx->multichannel != cifs_sb->ctx->multichannel) ||
> - (ctx->max_channels != cifs_sb->ctx->max_channels)) {
> -
> + if (need_mchan_update) {
> /* 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) {
> - spin_unlock(&ses->ses_lock);
> - mutex_unlock(&ses->session_mutex);
> - return -EINVAL;
> - }
> - ses->flags |= CIFS_SES_FLAG_SCALE_CHANNELS;
> - spin_unlock(&ses->ses_lock);
>
> mutex_unlock(&ses->session_mutex);
>
> - rc = smb3_update_ses_channels(ses, ses->server,
> - false /* from_reconnect */,
> - false /* disable_mchan */);
> + smb3_update_ses_channels(ses, ses->server,
> + false /* from_reconnect */,
> + false /* disable_mchan */);
>
> /* Clear scaling flag after operation */
> spin_lock(&ses->ses_lock);
> @@ -1197,22 +1244,30 @@ static int smb3_reconfigure(struct fs_context *fc)
> mutex_unlock(&ses->session_mutex);
> }
>
> - STEAL_STRING(cifs_sb, ctx, domainname);
> - STEAL_STRING(cifs_sb, ctx, nodename);
> - STEAL_STRING(cifs_sb, ctx, iocharset);
> -
> - /* if rsize or wsize not passed in on remount, use previous values */
> - ctx->rsize = rsize ? CIFS_ALIGN_RSIZE(fc, rsize) : cifs_sb->ctx->rsize;
> - ctx->wsize = wsize ? CIFS_ALIGN_WSIZE(fc, wsize) : cifs_sb->ctx->wsize;
> -
> smb3_cleanup_fs_context_contents(cifs_sb->ctx);
> - rc = smb3_fs_context_dup(cifs_sb->ctx, ctx);
> + memcpy(cifs_sb->ctx, new_ctx, sizeof(*new_ctx));
> + kfree(new_ctx);
> + new_ctx = NULL;
> + smb3_cleanup_fs_context(old_ctx);
> + old_ctx = NULL;
> smb3_update_mnt_flags(cifs_sb);
> #ifdef CONFIG_CIFS_DFS_UPCALL
> if (!rc)
> rc = dfs_cache_remount_fs(cifs_sb);
> #endif
>
> + return rc;
> +
> +cleanup_new_ctx:
> + smb3_cleanup_fs_context_contents(new_ctx);
> +restore_ctx:
> + kfree(new_ctx);
> + kfree_sensitive(new_password);
> + kfree_sensitive(new_password2);
> + smb3_cleanup_fs_context_contents(cifs_sb->ctx);
> + memcpy(cifs_sb->ctx, old_ctx, sizeof(*old_ctx));
> + kfree(old_ctx);
> +
> return rc;
> }
>
> --
> 2.43.0
>
>
--
Thanks,
Steve
© 2016 - 2026 Red Hat, Inc.