From: Sasha Levin <sashal@kernel.org>
To: stable@vger.kernel.org
Cc: Davide Ornaghi <d.ornaghi97@gmail.com>,
Namjae Jeon <linkinjeon@kernel.org>,
Steve French <stfrench@microsoft.com>,
Sasha Levin <sashal@kernel.org>
Subject: [PATCH 7.1.y] ksmbd: fix path resolution in ksmbd_vfs_kern_path_create
Date: Wed, 15 Jul 2026 21:45:17 -0400 [thread overview]
Message-ID: <20260716014517.777818-1-sashal@kernel.org> (raw)
In-Reply-To: <2026071457-shrank-luster-94bc@gregkh>
From: Davide Ornaghi <d.ornaghi97@gmail.com>
[ Upstream commit 1c8951963d8ed357f70f59e0ad4ddce2199d2016 ]
The SMB2 open lookup is rooted at the share with LOOKUP_BENEATH, but the
create/mkdir/hardlink sink is not: ksmbd_vfs_kern_path_create() builds an
absolute path with convert_to_unix_name() and resolves it from AT_FDCWD
via start_creating_path(), so a ".." component is walked from the real
filesystem root and escapes the export.
An authenticated client races a missing path component so the rooted open
lookup returns -ENOENT (taking the create branch) while the same component
is present (a directory) when the create walk runs; the create then
resolves ".." out of the share.
Root the create walk at the share like the lookup and rename paths already
are: resolve the parent with vfs_path_parent_lookup(..., LOOKUP_BENEATH,
&share_conf->vfs_path) and create the final component with
start_creating_noperm(). convert_to_unix_name() then has no callers and is
removed.
Fixes: 265fd1991c1d ("ksmbd: use LOOKUP_BENEATH to prevent the out of share access")
Cc: stable@vger.kernel.org
Signed-off-by: Davide Ornaghi <d.ornaghi97@gmail.com>
Acked-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Steve French <stfrench@microsoft.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
fs/smb/server/misc.c | 33 ---------------------------------
fs/smb/server/misc.h | 1 -
fs/smb/server/vfs.c | 33 +++++++++++++++++++++++++++------
3 files changed, 27 insertions(+), 40 deletions(-)
diff --git a/fs/smb/server/misc.c b/fs/smb/server/misc.c
index a543ec9d358177..966004c414a8c8 100644
--- a/fs/smb/server/misc.c
+++ b/fs/smb/server/misc.c
@@ -283,39 +283,6 @@ char *ksmbd_extract_sharename(struct unicode_map *um, const char *treename)
return ksmbd_casefold_sharename(um, name);
}
-/**
- * convert_to_unix_name() - convert windows name to unix format
- * @share: ksmbd_share_config pointer
- * @name: file name that is relative to share
- *
- * Return: converted name on success, otherwise NULL
- */
-char *convert_to_unix_name(struct ksmbd_share_config *share, const char *name)
-{
- int no_slash = 0, name_len, path_len;
- char *new_name;
-
- if (name[0] == '/')
- name++;
-
- path_len = share->path_sz;
- name_len = strlen(name);
- new_name = kmalloc(path_len + name_len + 2, KSMBD_DEFAULT_GFP);
- if (!new_name)
- return new_name;
-
- memcpy(new_name, share->path, path_len);
- if (new_name[path_len - 1] != '/') {
- new_name[path_len] = '/';
- no_slash = 1;
- }
-
- memcpy(new_name + path_len + no_slash, name, name_len);
- path_len += name_len + no_slash;
- new_name[path_len] = 0x00;
- return new_name;
-}
-
char *ksmbd_convert_dir_info_name(struct ksmbd_dir_info *d_info,
const struct nls_table *local_nls,
int *conv_len)
diff --git a/fs/smb/server/misc.h b/fs/smb/server/misc.h
index 13423696ae8c62..3909104e18ad48 100644
--- a/fs/smb/server/misc.h
+++ b/fs/smb/server/misc.h
@@ -25,7 +25,6 @@ void ksmbd_strip_last_slash(char *path);
void ksmbd_conv_path_to_windows(char *path);
char *ksmbd_casefold_sharename(struct unicode_map *um, const char *name);
char *ksmbd_extract_sharename(struct unicode_map *um, const char *treename);
-char *convert_to_unix_name(struct ksmbd_share_config *share, const char *name);
#define KSMBD_DIR_INFO_ALIGNMENT 8
struct ksmbd_dir_info;
diff --git a/fs/smb/server/vfs.c b/fs/smb/server/vfs.c
index d08973b288e581..5109ba5894490f 100644
--- a/fs/smb/server/vfs.c
+++ b/fs/smb/server/vfs.c
@@ -1251,15 +1251,36 @@ struct dentry *ksmbd_vfs_kern_path_create(struct ksmbd_work *work,
unsigned int flags,
struct path *path)
{
- char *abs_name;
+ struct ksmbd_share_config *share_conf = work->tcon->share_conf;
+ struct qstr last;
struct dentry *dent;
+ int err, type;
- abs_name = convert_to_unix_name(work->tcon->share_conf, name);
- if (!abs_name)
- return ERR_PTR(-ENOMEM);
+ /* resolve the name beneath the share root so ".." cannot escape */
+ CLASS(filename_kernel, filename)(name);
+
+ err = vfs_path_parent_lookup(filename, flags | LOOKUP_BENEATH,
+ path, &last, &type,
+ &share_conf->vfs_path);
+ if (err)
+ return ERR_PTR(err);
- dent = start_creating_path(AT_FDCWD, abs_name, path, flags);
- kfree(abs_name);
+ if (unlikely(type != LAST_NORM)) {
+ path_put(path);
+ return ERR_PTR(-EINVAL);
+ }
+
+ err = mnt_want_write(path->mnt);
+ if (err) {
+ path_put(path);
+ return ERR_PTR(err);
+ }
+
+ dent = start_creating_noperm(path->dentry, &last);
+ if (IS_ERR(dent)) {
+ mnt_drop_write(path->mnt);
+ path_put(path);
+ }
return dent;
}
--
2.53.0
prev parent reply other threads:[~2026-07-16 1:45 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-14 14:45 FAILED: patch "[PATCH] ksmbd: fix path resolution in ksmbd_vfs_kern_path_create" failed to apply to 7.1-stable tree gregkh
2026-07-16 1:45 ` Sasha Levin [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260716014517.777818-1-sashal@kernel.org \
--to=sashal@kernel.org \
--cc=d.ornaghi97@gmail.com \
--cc=linkinjeon@kernel.org \
--cc=stable@vger.kernel.org \
--cc=stfrench@microsoft.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox