]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
vfs: make LAST_XXX private to fs/namei.c
authorJori Koolstra <jkoolstra@xs4all.nl>
Thu, 28 May 2026 17:58:46 +0000 (17:58 +0000)
committerChristian Brauner <brauner@kernel.org>
Fri, 29 May 2026 07:47:02 +0000 (09:47 +0200)
The only user of LAST_XXX outside of fs/namei.c is fs/smb/server/vfs.c;
ksmbd_vfs_path_lookup() calls vfs_path_parent_lookup() and expects a
LAST_NORM last type (or it will be ENOENT). ksmbd_vfs_rename() also calls
vfs_path_parent_lookup() but forgets the LAST_NORM check.

It does not really make sense to have vfs_path_parent_lookup() expose
the last_type because it is only needed to ensure it is LAST_NORM. So
let's do this check in vfs_path_parent_lookup() instead and keep the
LAST_XXX internal to fs/namei.c. This changes the ENOENT errno in
ksmbd_vfs_path_lookup() to EINVAL, which matches better with how this is
handled by callers of filename_parentat().

Signed-off-by: Jori Koolstra <jkoolstra@xs4all.nl>
Link: https://patch.msgid.link/20260528175854.57626-1-jkoolstra@xs4all.nl
Reviewed-by: Amir Goldstein <amir73il@gmail.com>
Reviewed-by: NeilBrown <neil@brown.name>
Reviewed-by: Namjae Jeon <linkinjeon@kernel.org>
Signed-off-by: Christian Brauner (Amutable) <brauner@kernel.org>
fs/namei.c
fs/smb/server/vfs.c
include/linux/namei.h

index e1fe0f28b923649baf21c27ae2b470f1851f25a4..05291e6f4bbabf08280edd15aae4ca7d87fce1ab 100644 (file)
 static struct kmem_cache *__names_cache __ro_after_init;
 #define names_cache    runtime_const_ptr(__names_cache)
 
+/*
+ * Type of the last component on LOOKUP_PARENT
+ */
+enum {LAST_NORM, LAST_ROOT, LAST_DOT, LAST_DOTDOT};
+
 void __init filename_init(void)
 {
        __names_cache = kmem_cache_create_usercopy("names_cache", sizeof(struct filename), 0,
@@ -3051,15 +3056,22 @@ EXPORT_SYMBOL(kern_path);
  * @flags: lookup flags
  * @parent: pointer to struct path to fill
  * @last: last component
- * @type: type of the last component
  * @root: pointer to struct path of the base directory
  */
 int vfs_path_parent_lookup(struct filename *filename, unsigned int flags,
-                          struct path *parent, struct qstr *last, int *type,
+                          struct path *parent, struct qstr *last,
                           const struct path *root)
 {
-       return  __filename_parentat(AT_FDCWD, filename, flags, parent, last,
-                                   type, root);
+       int type;
+       int err =  __filename_parentat(AT_FDCWD, filename, flags, parent, last,
+                                      &type, root);
+       if (err)
+               return err;
+       if (unlikely(type != LAST_NORM)) {
+               path_put(parent);
+               return -EINVAL;
+       }
+       return 0;
 }
 EXPORT_SYMBOL(vfs_path_parent_lookup);
 
index d08973b288e5819a11488445c7e9a10ff11ae3d9..cd1dbca0cffbfcae437ab9fe6dc6eabecbae7a0e 100644 (file)
@@ -19,7 +19,6 @@
 #include <linux/vmalloc.h>
 #include <linux/sched/xacct.h>
 #include <linux/crc32c.h>
-#include <linux/namei.h>
 #include <linux/splice.h>
 
 #include "glob.h"
@@ -56,7 +55,7 @@ static int ksmbd_vfs_path_lookup(struct ksmbd_share_config *share_conf,
 {
        struct qstr last;
        const struct path *root_share_path = &share_conf->vfs_path;
-       int err, type;
+       int err;
        struct dentry *d;
 
        if (pathname[0] == '\0') {
@@ -67,17 +66,11 @@ static int ksmbd_vfs_path_lookup(struct ksmbd_share_config *share_conf,
        }
 
        CLASS(filename_kernel, filename)(pathname);
-       err = vfs_path_parent_lookup(filename, flags,
-                                    path, &last, &type,
+       err = vfs_path_parent_lookup(filename, flags, path, &last,
                                     root_share_path);
        if (err)
                return err;
 
-       if (unlikely(type != LAST_NORM)) {
-               path_put(path);
-               return -ENOENT;
-       }
-
        if (for_remove) {
                err = mnt_want_write(path->mnt);
                if (err) {
@@ -668,7 +661,6 @@ int ksmbd_vfs_rename(struct ksmbd_work *work, const struct path *old_path,
        struct renamedata rd;
        struct ksmbd_share_config *share_conf = work->tcon->share_conf;
        struct ksmbd_file *parent_fp;
-       int new_type;
        int err, lookup_flags = LOOKUP_NO_SYMLINKS;
 
        if (ksmbd_override_fsids(work))
@@ -678,8 +670,7 @@ int ksmbd_vfs_rename(struct ksmbd_work *work, const struct path *old_path,
 
 retry:
        err = vfs_path_parent_lookup(to, lookup_flags | LOOKUP_BENEATH,
-                                    &new_path, &new_last, &new_type,
-                                    &share_conf->vfs_path);
+                                    &new_path, &new_last, &share_conf->vfs_path);
        if (err)
                goto out1;
 
index 2ad6dd9987b905605d30ba7281e40caa850bf887..3941b9f1dec72ed76e7c9789501e4c3716b73461 100644 (file)
@@ -13,11 +13,6 @@ enum { MAX_NESTED_LINKS = 8 };
 
 #define MAXSYMLINKS 40
 
-/*
- * Type of the last component on LOOKUP_PARENT
- */
-enum {LAST_NORM, LAST_ROOT, LAST_DOT, LAST_DOTDOT};
-
 /* pathwalk mode */
 #define LOOKUP_FOLLOW          BIT(0)  /* follow links at the end */
 #define LOOKUP_DIRECTORY       BIT(1)  /* require a directory */
@@ -67,7 +62,7 @@ static inline void end_removing_path(const struct path *path , struct dentry *de
        end_creating_path(path, dentry);
 }
 int vfs_path_parent_lookup(struct filename *filename, unsigned int flags,
-                          struct path *parent, struct qstr *last, int *type,
+                          struct path *parent, struct qstr *last,
                           const struct path *root);
 int vfs_path_lookup(struct dentry *, struct vfsmount *, const char *,
                    unsigned int, struct path *);