[PATCH] smb: client: fix memory corruption in smb3_reconfigure()

Fredric Cover posted 1 patch 6 days, 3 hours ago
fs/smb/client/fs_context.c | 15 +++++++++++----
1 file changed, 11 insertions(+), 4 deletions(-)
[PATCH] smb: client: fix memory corruption in smb3_reconfigure()
Posted by Fredric Cover 6 days, 3 hours ago
From: Fredric Cover <fredric.cover.lkernel@gmail.com>

smb3_reconfigure() modifies the active volume context directly.
If smb3_fs_context_dup() fails to allocate space when copying strings
of a new context into the volume context, it clears the volume context.

Add staging logic (tmp_ctx) to ensure that either the volume context
stays the same on errors or is updated with the new state, and is
never cleared.

Signed-off-by: Fredric Cover <fredric.cover.lkernel@gmail.com>
---
 fs/smb/client/fs_context.c | 15 +++++++++++----
 1 file changed, 11 insertions(+), 4 deletions(-)

diff --git a/fs/smb/client/fs_context.c b/fs/smb/client/fs_context.c
index b9544eb03..3a6f207a5 100644
--- a/fs/smb/client/fs_context.c
+++ b/fs/smb/client/fs_context.c
@@ -1082,6 +1082,7 @@ 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 *tmp_ctx; /* used for copy of ctx to cifs_sb->ctx */
 	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;
@@ -1205,13 +1206,19 @@ static int smb3_reconfigure(struct fs_context *fc)
 	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);
-	smb3_update_mnt_flags(cifs_sb);
+	tmp_ctx = kzalloc_obj(*tmp_ctx, GFP_KERNEL);
+	if (!tmp_ctx)
+		return -ENOMEM;
+	rc = smb3_fs_context_dup(tmp_ctx, ctx);
+	if (!rc) {
+		smb3_cleanup_fs_context_contents(cifs_sb->ctx);
+		memcpy(cifs_sb->ctx, tmp_ctx, sizeof(*tmp_ctx));
+		smb3_update_mnt_flags(cifs_sb);
 #ifdef CONFIG_CIFS_DFS_UPCALL
-	if (!rc)
 		rc = dfs_cache_remount_fs(cifs_sb);
 #endif
+	}
+	kfree(tmp_ctx);
 
 	return rc;
 }
-- 
2.53.0
Re: [PATCH] smb: client: fix memory corruption in smb3_reconfigure()
Posted by Fredric Cover 5 days, 2 hours ago
Hello Steve and list,

Please disregard this patch. I see that DaeMyung's patch series
("cifs: client: stage smb3_reconfigure() updates and restore ctx on failure")
was merged into 7.1-rc4, which addresses this exact state-corruption path.

Apologies for the noise.

Best regards,
Fredric Cover

On Mon, May 18, 2026 at 5:14 PM Fredric Cover
<fredric.cover.lkernel@gmail.com> wrote:
>
> From: Fredric Cover <fredric.cover.lkernel@gmail.com>
>
> smb3_reconfigure() modifies the active volume context directly.
> If smb3_fs_context_dup() fails to allocate space when copying strings
> of a new context into the volume context, it clears the volume context.
>
> Add staging logic (tmp_ctx) to ensure that either the volume context
> stays the same on errors or is updated with the new state, and is
> never cleared.
>
> Signed-off-by: Fredric Cover <fredric.cover.lkernel@gmail.com>
> ---
>  fs/smb/client/fs_context.c | 15 +++++++++++----
>  1 file changed, 11 insertions(+), 4 deletions(-)
>
> diff --git a/fs/smb/client/fs_context.c b/fs/smb/client/fs_context.c
> index b9544eb03..3a6f207a5 100644
> --- a/fs/smb/client/fs_context.c
> +++ b/fs/smb/client/fs_context.c
> @@ -1082,6 +1082,7 @@ 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 *tmp_ctx; /* used for copy of ctx to cifs_sb->ctx */
>         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;
> @@ -1205,13 +1206,19 @@ static int smb3_reconfigure(struct fs_context *fc)
>         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);
> -       smb3_update_mnt_flags(cifs_sb);
> +       tmp_ctx = kzalloc_obj(*tmp_ctx, GFP_KERNEL);
> +       if (!tmp_ctx)
> +               return -ENOMEM;
> +       rc = smb3_fs_context_dup(tmp_ctx, ctx);
> +       if (!rc) {
> +               smb3_cleanup_fs_context_contents(cifs_sb->ctx);
> +               memcpy(cifs_sb->ctx, tmp_ctx, sizeof(*tmp_ctx));
> +               smb3_update_mnt_flags(cifs_sb);
>  #ifdef CONFIG_CIFS_DFS_UPCALL
> -       if (!rc)
>                 rc = dfs_cache_remount_fs(cifs_sb);
>  #endif
> +       }
> +       kfree(tmp_ctx);
>
>         return rc;
>  }
> --
> 2.53.0
>