+++ /dev/null
-From d5a863a153e90996ab2aef6b9e08d509f4d5662b Mon Sep 17 00:00:00 2001
-From: Paulo Alcantara <pc@manguebit.com>
-Date: Sun, 16 Apr 2023 15:38:28 -0300
-Subject: cifs: avoid dup prefix path in dfs_get_automount_devname()
-
-From: Paulo Alcantara <pc@manguebit.com>
-
-commit d5a863a153e90996ab2aef6b9e08d509f4d5662b upstream.
-
-@server->origin_fullpath already contains the tree name + optional
-prefix, so avoid calling __build_path_from_dentry_optional_prefix() as
-it might end up duplicating prefix path from @cifs_sb->prepath into
-final full path.
-
-Instead, generate DFS full path by simply merging
-@server->origin_fullpath with dentry's path.
-
-This fixes the following case
-
- mount.cifs //root/dfs/dir /mnt/ -o ...
- ls /mnt/link
-
-where cifs_dfs_do_automount() will call smb3_parse_devname() with
-@devname set to "//root/dfs/dir/link" instead of
-"//root/dfs/dir/dir/link".
-
-Fixes: 7ad54b98fc1f ("cifs: use origin fullpath for automounts")
-Cc: <stable@vger.kernel.org> # 6.2+
-Signed-off-by: Paulo Alcantara (SUSE) <pc@manguebit.com>
-Signed-off-by: Steve French <stfrench@microsoft.com>
-Cc: Andrew Paniakin <apanyaki@amazon.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- fs/smb/client/cifs_dfs_ref.c | 2 --
- fs/smb/client/cifsproto.h | 18 ++++++++++++++++++
- 2 files changed, 18 insertions(+), 2 deletions(-)
-
---- a/fs/smb/client/cifs_dfs_ref.c
-+++ b/fs/smb/client/cifs_dfs_ref.c
-@@ -325,8 +325,6 @@ static struct vfsmount *cifs_dfs_do_auto
- mnt = ERR_CAST(full_path);
- goto out;
- }
--
-- convert_delimiter(full_path, '/');
- cifs_dbg(FYI, "%s: full_path: %s\n", __func__, full_path);
-
- tmp = *cur_ctx;
---- a/fs/smb/client/cifsproto.h
-+++ b/fs/smb/client/cifsproto.h
-@@ -62,11 +62,14 @@ char *__build_path_from_dentry_optional_
- bool prefix);
- extern char *build_path_from_dentry_optional_prefix(struct dentry *direntry,
- void *page, bool prefix);
-+/* Return DFS full path out of a dentry set for automount */
- static inline char *dfs_get_automount_devname(struct dentry *dentry, void *page)
- {
- struct cifs_sb_info *cifs_sb = CIFS_SB(dentry->d_sb);
- struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
- struct TCP_Server_Info *server = tcon->ses->server;
-+ size_t len;
-+ char *s;
-
- if (unlikely(!server->origin_fullpath))
- return ERR_PTR(-EREMOTE);
-@@ -75,6 +78,21 @@ static inline char *dfs_get_automount_de
- server->origin_fullpath,
- strlen(server->origin_fullpath),
- true);
-+ s = dentry_path_raw(dentry, page, PATH_MAX);
-+ if (IS_ERR(s))
-+ return s;
-+ /* for root, we want "" */
-+ if (!s[1])
-+ s++;
-+
-+ len = strlen(server->origin_fullpath);
-+ if (s < (char *)page + len)
-+ return ERR_PTR(-ENAMETOOLONG);
-+
-+ s -= len;
-+ memcpy(s, server->origin_fullpath, len);
-+ convert_delimiter(s, '/');
-+ return s;
- }
-
- static inline void *alloc_dentry_path(void)
+++ /dev/null
-From 7ad54b98fc1f141cfb70cfe2a3d6def5a85169ff Mon Sep 17 00:00:00 2001
-From: Paulo Alcantara <pc@cjr.nz>
-Date: Sun, 18 Dec 2022 14:37:32 -0300
-Subject: cifs: use origin fullpath for automounts
-
-From: Paulo Alcantara <pc@cjr.nz>
-
-commit 7ad54b98fc1f141cfb70cfe2a3d6def5a85169ff upstream.
-
-Use TCP_Server_Info::origin_fullpath instead of cifs_tcon::tree_name
-when building source paths for automounts as it will be useful for
-domain-based DFS referrals where the connections and referrals would
-get either re-used from the cache or re-created when chasing the dfs
-link.
-
-Signed-off-by: Paulo Alcantara (SUSE) <pc@cjr.nz>
-Signed-off-by: Steve French <stfrench@microsoft.com>
-[apanyaki: backport to v6.1-stable]
-Signed-off-by: Andrew Paniakin <apanyaki@amazon.com>
-Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
----
- fs/smb/client/cifs_dfs_ref.c | 34 ++++++++++++++++++++++++++++++++--
- fs/smb/client/cifsproto.h | 18 ++++++++++++++++++
- fs/smb/client/dir.c | 21 +++++++++++++++------
- 3 files changed, 65 insertions(+), 8 deletions(-)
-
---- a/fs/smb/client/cifs_dfs_ref.c
-+++ b/fs/smb/client/cifs_dfs_ref.c
-@@ -258,6 +258,31 @@ compose_mount_options_err:
- goto compose_mount_options_out;
- }
-
-+static int set_dest_addr(struct smb3_fs_context *ctx, const char *full_path)
-+{
-+ struct sockaddr *addr = (struct sockaddr *)&ctx->dstaddr;
-+ char *str_addr = NULL;
-+ int rc;
-+
-+ rc = dns_resolve_server_name_to_ip(full_path, &str_addr, NULL);
-+ if (rc < 0)
-+ goto out;
-+
-+ rc = cifs_convert_address(addr, str_addr, strlen(str_addr));
-+ if (!rc) {
-+ cifs_dbg(FYI, "%s: failed to convert ip address\n", __func__);
-+ rc = -EINVAL;
-+ goto out;
-+ }
-+
-+ cifs_set_port(addr, ctx->port);
-+ rc = 0;
-+
-+out:
-+ kfree(str_addr);
-+ return rc;
-+}
-+
- /*
- * Create a vfsmount that we can automount
- */
-@@ -295,8 +320,7 @@ static struct vfsmount *cifs_dfs_do_auto
- ctx = smb3_fc2context(fc);
-
- page = alloc_dentry_path();
-- /* always use tree name prefix */
-- full_path = build_path_from_dentry_optional_prefix(mntpt, page, true);
-+ full_path = dfs_get_automount_devname(mntpt, page);
- if (IS_ERR(full_path)) {
- mnt = ERR_CAST(full_path);
- goto out;
-@@ -313,6 +337,12 @@ static struct vfsmount *cifs_dfs_do_auto
- if (rc) {
- mnt = ERR_PTR(rc);
- goto out;
-+ }
-+
-+ rc = set_dest_addr(ctx, full_path);
-+ if (rc) {
-+ mnt = ERR_PTR(rc);
-+ goto out;
- }
-
- rc = smb3_parse_devname(full_path, ctx);
---- a/fs/smb/client/cifsproto.h
-+++ b/fs/smb/client/cifsproto.h
-@@ -57,8 +57,26 @@ extern void exit_cifs_idmap(void);
- extern int init_cifs_spnego(void);
- extern void exit_cifs_spnego(void);
- extern const char *build_path_from_dentry(struct dentry *, void *);
-+char *__build_path_from_dentry_optional_prefix(struct dentry *direntry, void *page,
-+ const char *tree, int tree_len,
-+ bool prefix);
- extern char *build_path_from_dentry_optional_prefix(struct dentry *direntry,
- void *page, bool prefix);
-+static inline char *dfs_get_automount_devname(struct dentry *dentry, void *page)
-+{
-+ struct cifs_sb_info *cifs_sb = CIFS_SB(dentry->d_sb);
-+ struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
-+ struct TCP_Server_Info *server = tcon->ses->server;
-+
-+ if (unlikely(!server->origin_fullpath))
-+ return ERR_PTR(-EREMOTE);
-+
-+ return __build_path_from_dentry_optional_prefix(dentry, page,
-+ server->origin_fullpath,
-+ strlen(server->origin_fullpath),
-+ true);
-+}
-+
- static inline void *alloc_dentry_path(void)
- {
- return __getname();
---- a/fs/smb/client/dir.c
-+++ b/fs/smb/client/dir.c
-@@ -78,14 +78,13 @@ build_path_from_dentry(struct dentry *di
- prefix);
- }
-
--char *
--build_path_from_dentry_optional_prefix(struct dentry *direntry, void *page,
-- bool prefix)
-+char *__build_path_from_dentry_optional_prefix(struct dentry *direntry, void *page,
-+ const char *tree, int tree_len,
-+ bool prefix)
- {
- int dfsplen;
- int pplen = 0;
- struct cifs_sb_info *cifs_sb = CIFS_SB(direntry->d_sb);
-- struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
- char dirsep = CIFS_DIR_SEP(cifs_sb);
- char *s;
-
-@@ -93,7 +92,7 @@ build_path_from_dentry_optional_prefix(s
- return ERR_PTR(-ENOMEM);
-
- if (prefix)
-- dfsplen = strnlen(tcon->tree_name, MAX_TREE_SIZE + 1);
-+ dfsplen = strnlen(tree, tree_len + 1);
- else
- dfsplen = 0;
-
-@@ -123,7 +122,7 @@ build_path_from_dentry_optional_prefix(s
- }
- if (dfsplen) {
- s -= dfsplen;
-- memcpy(s, tcon->tree_name, dfsplen);
-+ memcpy(s, tree, dfsplen);
- if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_POSIX_PATHS) {
- int i;
- for (i = 0; i < dfsplen; i++) {
-@@ -135,6 +134,16 @@ build_path_from_dentry_optional_prefix(s
- return s;
- }
-
-+char *build_path_from_dentry_optional_prefix(struct dentry *direntry, void *page,
-+ bool prefix)
-+{
-+ struct cifs_sb_info *cifs_sb = CIFS_SB(direntry->d_sb);
-+ struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
-+
-+ return __build_path_from_dentry_optional_prefix(direntry, page, tcon->tree_name,
-+ MAX_TREE_SIZE, prefix);
-+}
-+
- /*
- * Don't allow path components longer than the server max.
- * Don't allow the separator character in a path component.