Unfortunately we can't kfree() the UNC and prefix paths in cifs_smb3_do_mount() because they could have come from a chased DFS referral (automount) and we rely on the new values set in cifs_sb->ctx prior to calling cifs_mount(). Instead, fix smb3_parse_devname() to not leak the UNC and prefix paths when parsing new share paths. Cc: <stable@xxxxxxxxxxxxxxx> # v5.11+ Fixes: 315db9a05b7a ("cifs: fix leak in cifs_smb3_do_mount() ctx") Signed-off-by: Paulo Alcantara (SUSE) <pc@xxxxxx> --- fs/cifs/cifsfs.c | 6 ------ fs/cifs/connect.c | 10 +++++++--- fs/cifs/fs_context.c | 2 ++ 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 8a6894577697..bfe98136f9c1 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -863,12 +863,6 @@ cifs_smb3_do_mount(struct file_system_type *fs_type, goto out; } - /* cifs_setup_volume_info->smb3_parse_devname() redups UNC & prepath */ - kfree(cifs_sb->ctx->UNC); - cifs_sb->ctx->UNC = NULL; - kfree(cifs_sb->ctx->prepath); - cifs_sb->ctx->prepath = NULL; - rc = cifs_setup_volume_info(cifs_sb->ctx, NULL, old_ctx->UNC); if (rc) { root = ERR_PTR(rc); diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index becd5f807787..ee4a92cbcb29 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -3159,9 +3159,13 @@ static int do_dfs_failover(const char *path, const char *full_path, struct cifs_ int cifs_setup_volume_info(struct smb3_fs_context *ctx, const char *mntopts, const char *devname) { - int rc = 0; + int rc; - smb3_parse_devname(devname, ctx); + rc = smb3_parse_devname(devname, ctx); + if (rc) { + cifs_dbg(VFS, "%s: failed to parse %s: %d\n", __func__, devname, rc); + return rc; + } if (mntopts) { char *ip; @@ -3189,7 +3193,7 @@ cifs_setup_volume_info(struct smb3_fs_context *ctx, const char *mntopts, const c return -EINVAL; } - return rc; + return 0; } static int diff --git a/fs/cifs/fs_context.c b/fs/cifs/fs_context.c index 1d6e0e15b034..b502a44e15a1 100644 --- a/fs/cifs/fs_context.c +++ b/fs/cifs/fs_context.c @@ -476,6 +476,7 @@ smb3_parse_devname(const char *devname, struct smb3_fs_context *ctx) /* move "pos" up to delimiter or NULL */ pos += len; + kfree(ctx->UNC); ctx->UNC = kstrndup(devname, pos - devname, GFP_KERNEL); if (!ctx->UNC) return -ENOMEM; @@ -490,6 +491,7 @@ smb3_parse_devname(const char *devname, struct smb3_fs_context *ctx) if (!*pos) return 0; + kfree(ctx->prepath); ctx->prepath = kstrdup(pos, GFP_KERNEL); if (!ctx->prepath) return -ENOMEM; -- 2.31.1