FAILED: patch "[PATCH] ksmbd: fix path resolution in ksmbd_vfs_kern_path_create" failed to apply to 7.1-stable tree
Subsystems (2)
[email protected]
maintainerThe patch below does not apply to the 7.1-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
To reproduce the conflict and resubmit, you may use the following commands:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-7.1.y
git checkout FETCH_HEAD
git cherry-pick -x 1c8951963d8ed357f70f59e0ad4ddce2199d2016
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<[email protected]>' --in-reply-to '2026071457-shrank-luster-94bc@gregkh' --subject-prefix 'PATCH 7.1.y' 'HEAD^..'
Possible dependencies:
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From 1c8951963d8ed357f70f59e0ad4ddce2199d2016 Mon Sep 17 00:00:00 2001
From: Davide Ornaghi <[email protected]>
Date: Mon, 15 Jun 2026 20:35:01 +0900
Subject: [PATCH] ksmbd: fix path resolution in ksmbd_vfs_kern_path_create
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.
fs/smb/server/misc.c +0 -33
@@ -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)
fs/smb/server/misc.h +0 -1
@@ -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 8struct ksmbd_dir_info ;
fs/smb/server/vfs.c +21 -6
@@ -1259,15 +1259,30 @@ 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; - 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); - dent =start_creating_path (AT_FDCWD , abs_name, path, flags); -kfree (abs_name); + err =vfs_path_parent_lookup (filename, flags |LOOKUP_BENEATH , + path, &last, &share_conf->vfs_path); +if (err) +return ERR_PTR (err); + + 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; }
Sasha Levin
maintainerPATCH 1/1 ksmbd: fix path resolution in ksmbd_vfs_kern_path_create
From: Davide Ornaghi <[email protected]>
[ 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.
--- 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(-)
fs/smb/server/misc.c +0 -33
@@ -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)
fs/smb/server/misc.h +0 -1
@@ -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 8struct ksmbd_dir_info ;
fs/smb/server/vfs.c +27 -6
@@ -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; }
Signature · 1 line
2.53.0