Re: [PATCH] smb: client: fix missed ses refcounting

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Tentatively merged into cifs-2.6.git for-next pending testing

On Tue, Jul 11, 2023 at 12:15 PM Paulo Alcantara <pc@xxxxxxxxxxxxx> wrote:
>
> Use new cifs_smb_ses_inc_refcount() helper to get an active reference
> of @ses and @ses->dfs_root_ses (if set).  This will prevent
> @ses->dfs_root_ses of being put in the next call to cifs_put_smb_ses()
> and thus potentially causing an use-after-free bug.
>
> Fixes: 8e3554150d6c ("cifs: fix sharing of DFS connections")
> Signed-off-by: Paulo Alcantara (SUSE) <pc@xxxxxxxxxxxxx>
> ---
>  fs/smb/client/dfs.c           | 26 ++++++++++----------------
>  fs/smb/client/smb2transport.c |  2 +-
>  2 files changed, 11 insertions(+), 17 deletions(-)
>
> diff --git a/fs/smb/client/dfs.c b/fs/smb/client/dfs.c
> index 1403a2d1ab17..df3fd3b720da 100644
> --- a/fs/smb/client/dfs.c
> +++ b/fs/smb/client/dfs.c
> @@ -66,6 +66,12 @@ static int get_session(struct cifs_mount_ctx *mnt_ctx, const char *full_path)
>         return rc;
>  }
>
> +/*
> + * Track individual DFS referral servers used by new DFS mount.
> + *
> + * On success, their lifetime will be shared by final tcon (dfs_ses_list).
> + * Otherwise, they will be put by dfs_put_root_smb_sessions() in cifs_mount().
> + */
>  static int add_root_smb_session(struct cifs_mount_ctx *mnt_ctx)
>  {
>         struct smb3_fs_context *ctx = mnt_ctx->fs_ctx;
> @@ -80,11 +86,12 @@ static int add_root_smb_session(struct cifs_mount_ctx *mnt_ctx)
>                 INIT_LIST_HEAD(&root_ses->list);
>
>                 spin_lock(&cifs_tcp_ses_lock);
> -               ses->ses_count++;
> +               cifs_smb_ses_inc_refcount(ses);
>                 spin_unlock(&cifs_tcp_ses_lock);
>                 root_ses->ses = ses;
>                 list_add_tail(&root_ses->list, &mnt_ctx->dfs_ses_list);
>         }
> +       /* Select new DFS referral server so that new referrals go through it */
>         ctx->dfs_root_ses = ses;
>         return 0;
>  }
> @@ -242,7 +249,6 @@ static int __dfs_mount_share(struct cifs_mount_ctx *mnt_ctx)
>  int dfs_mount_share(struct cifs_mount_ctx *mnt_ctx, bool *isdfs)
>  {
>         struct smb3_fs_context *ctx = mnt_ctx->fs_ctx;
> -       struct cifs_ses *ses;
>         bool nodfs = ctx->nodfs;
>         int rc;
>
> @@ -276,20 +282,8 @@ int dfs_mount_share(struct cifs_mount_ctx *mnt_ctx, bool *isdfs)
>         }
>
>         *isdfs = true;
> -       /*
> -        * Prevent DFS root session of being put in the first call to
> -        * cifs_mount_put_conns().  If another DFS root server was not found
> -        * while chasing the referrals (@ctx->dfs_root_ses == @ses), then we
> -        * can safely put extra refcount of @ses.
> -        */
> -       ses = mnt_ctx->ses;
> -       mnt_ctx->ses = NULL;
> -       mnt_ctx->server = NULL;
> -       rc = __dfs_mount_share(mnt_ctx);
> -       if (ses == ctx->dfs_root_ses)
> -               cifs_put_smb_ses(ses);
> -
> -       return rc;
> +       add_root_smb_session(mnt_ctx);
> +       return __dfs_mount_share(mnt_ctx);
>  }
>
>  /* Update dfs referral path of superblock */
> diff --git a/fs/smb/client/smb2transport.c b/fs/smb/client/smb2transport.c
> index c6db898dab7c..7676091b3e77 100644
> --- a/fs/smb/client/smb2transport.c
> +++ b/fs/smb/client/smb2transport.c
> @@ -160,7 +160,7 @@ smb2_find_smb_ses_unlocked(struct TCP_Server_Info *server, __u64 ses_id)
>                         spin_unlock(&ses->ses_lock);
>                         continue;
>                 }
> -               ++ses->ses_count;
> +               cifs_smb_ses_inc_refcount(ses);
>                 spin_unlock(&ses->ses_lock);
>                 return ses;
>         }
> --
> 2.41.0
>


-- 
Thanks,

Steve




[Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux