From: Song Liu <song@kernel.org>
To: bpf@vger.kernel.org, linux-fsdevel@vger.kernel.org,
linux-kernel@vger.kernel.org,
linux-security-module@vger.kernel.org
Cc: kernel-team@meta.com, andrii@kernel.org, eddyz87@gmail.com,
ast@kernel.org, daniel@iogearbox.net, martin.lau@linux.dev,
viro@zeniv.linux.org.uk, brauner@kernel.org, jack@suse.cz,
kpsingh@kernel.org, mattbobrowski@google.com, m@maowtm.org,
neil@brown.name, Song Liu <song@kernel.org>
Subject: [PATCH v5 bpf-next 1/5] namei: Introduce new helper function path_walk_parent()
Date: Mon, 16 Jun 2025 23:11:12 -0700 [thread overview]
Message-ID: <20250617061116.3681325-2-song@kernel.org> (raw)
In-Reply-To: <20250617061116.3681325-1-song@kernel.org>
This helper walks an input path to its parent. Logic are added to handle
walking across mount tree.
This will be used by landlock, and BPF LSM.
Suggested-by: Neil Brown <neil@brown.name>
Signed-off-by: Song Liu <song@kernel.org>
---
fs/namei.c | 95 +++++++++++++++++++++++++++++++++++--------
include/linux/namei.h | 2 +
2 files changed, 79 insertions(+), 18 deletions(-)
diff --git a/fs/namei.c b/fs/namei.c
index 4bb889fc980b..d0557c0b5cc8 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -2048,36 +2048,95 @@ static struct dentry *follow_dotdot_rcu(struct nameidata *nd)
return nd->path.dentry;
}
-static struct dentry *follow_dotdot(struct nameidata *nd)
+/**
+ * __path_walk_parent - Find the parent of the given struct path
+ * @path - The struct path to start from
+ * @root - A struct path which serves as a boundary not to be crosses.
+ * - If @root is zero'ed, walk all the way to global root.
+ * @flags - Some LOOKUP_ flags.
+ *
+ * Find and return the dentry for the parent of the given path
+ * (mount/dentry). If the given path is the root of a mounted tree, it
+ * is first updated to the mount point on which that tree is mounted.
+ *
+ * If %LOOKUP_NO_XDEV is given, then *after* the path is updated to a new
+ * mount, the error EXDEV is returned.
+ *
+ * If no parent can be found, either because the tree is not mounted or
+ * because the @path matches the @root, then @path->dentry is returned
+ * unless @flags contains %LOOKUP_BENEATH, in which case -EXDEV is returned.
+ *
+ * Returns: either an ERR_PTR() or the chosen parent which will have had
+ * the refcount incremented.
+ */
+static struct dentry *__path_walk_parent(struct path *path, const struct path *root, int flags)
{
- struct dentry *parent;
-
- if (path_equal(&nd->path, &nd->root))
+ if (path_equal(path, root))
goto in_root;
- if (unlikely(nd->path.dentry == nd->path.mnt->mnt_root)) {
- struct path path;
+ if (unlikely(path->dentry == path->mnt->mnt_root)) {
+ struct path new_path;
- if (!choose_mountpoint(real_mount(nd->path.mnt),
- &nd->root, &path))
+ if (!choose_mountpoint(real_mount(path->mnt),
+ root, &new_path))
goto in_root;
- path_put(&nd->path);
- nd->path = path;
- nd->inode = path.dentry->d_inode;
- if (unlikely(nd->flags & LOOKUP_NO_XDEV))
+ path_put(path);
+ *path = new_path;
+ if (unlikely(flags & LOOKUP_NO_XDEV))
return ERR_PTR(-EXDEV);
}
/* rare case of legitimate dget_parent()... */
- parent = dget_parent(nd->path.dentry);
+ return dget_parent(path->dentry);
+
+in_root:
+ if (unlikely(flags & LOOKUP_BENEATH))
+ return ERR_PTR(-EXDEV);
+ return dget(path->dentry);
+}
+
+/**
+ * path_walk_parent - Walk to the parent of path
+ * @path: input and output path.
+ * @root: root of the path walk, do not go beyond this root. If @root is
+ * zero'ed, walk all the way to real root.
+ *
+ * Given a path, find the parent path. Replace @path with the parent path.
+ * If we were already at the real root or a disconnected root, @path is
+ * not changed.
+ *
+ * Returns:
+ * 0 - if @path is updated to its parent.
+ * <0 - if @path is already the root (real root or @root).
+ */
+int path_walk_parent(struct path *path, const struct path *root)
+{
+ struct dentry *parent;
+
+ parent = __path_walk_parent(path, root, LOOKUP_BENEATH);
+
+ if (IS_ERR(parent))
+ return PTR_ERR(parent);
+
+ if (parent == path->dentry) {
+ dput(parent);
+ return -ENOENT;
+ }
+ dput(path->dentry);
+ path->dentry = parent;
+ return 0;
+}
+
+static struct dentry *follow_dotdot(struct nameidata *nd)
+{
+ struct dentry *parent = __path_walk_parent(&nd->path, &nd->root, nd->flags);
+
+ if (IS_ERR(parent))
+ return parent;
if (unlikely(!path_connected(nd->path.mnt, parent))) {
dput(parent);
return ERR_PTR(-ENOENT);
}
+ nd->inode = nd->path.dentry->d_inode;
return parent;
-
-in_root:
- if (unlikely(nd->flags & LOOKUP_BENEATH))
- return ERR_PTR(-EXDEV);
- return dget(nd->path.dentry);
}
static const char *handle_dots(struct nameidata *nd, int type)
diff --git a/include/linux/namei.h b/include/linux/namei.h
index 5d085428e471..ca68fa4089e0 100644
--- a/include/linux/namei.h
+++ b/include/linux/namei.h
@@ -85,6 +85,8 @@ extern int follow_down_one(struct path *);
extern int follow_down(struct path *path, unsigned int flags);
extern int follow_up(struct path *);
+int path_walk_parent(struct path *path, const struct path *root);
+
extern struct dentry *lock_rename(struct dentry *, struct dentry *);
extern struct dentry *lock_rename_child(struct dentry *, struct dentry *);
extern void unlock_rename(struct dentry *, struct dentry *);
--
2.47.1
next prev parent reply other threads:[~2025-06-17 6:11 UTC|newest]
Thread overview: 50+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-06-17 6:11 [PATCH v5 bpf-next 0/5] bpf path iterator Song Liu
2025-06-17 6:11 ` Song Liu [this message]
2025-06-18 1:02 ` [PATCH v5 bpf-next 1/5] namei: Introduce new helper function path_walk_parent() kernel test robot
2025-06-24 12:18 ` Jan Kara
2025-06-24 17:37 ` Song Liu
2025-06-25 10:30 ` Jan Kara
2025-07-04 17:40 ` Yonghong Song
2025-07-06 23:54 ` Song Liu
2025-07-07 17:53 ` Yonghong Song
2025-06-17 6:11 ` [PATCH v5 bpf-next 2/5] landlock: Use path_walk_parent() Song Liu
2025-07-03 18:29 ` Mickaël Salaün
2025-07-03 22:27 ` Song Liu
2025-07-04 9:00 ` Mickaël Salaün
2025-07-06 22:29 ` Song Liu
2025-07-07 10:28 ` Christian Brauner
2025-06-17 6:11 ` [PATCH v5 bpf-next 3/5] bpf: Introduce path iterator Song Liu
2025-06-17 6:11 ` [PATCH v5 bpf-next 4/5] selftests/bpf: Add tests for bpf " Song Liu
2025-06-17 6:11 ` [PATCH v5 bpf-next 5/5] selftests/bpf: Path walk test Song Liu
2025-06-20 21:59 ` [PATCH v5 bpf-next 0/5] bpf path iterator Song Liu
2025-06-24 18:45 ` Mickaël Salaün
2025-06-24 21:38 ` NeilBrown
2025-06-25 13:14 ` Mickaël Salaün
2025-06-25 23:04 ` NeilBrown
2025-06-25 23:17 ` Song Liu
2025-06-26 0:07 ` Tingmao Wang
2025-06-26 1:05 ` NeilBrown
2025-06-26 5:52 ` Song Liu
2025-06-26 9:43 ` Mickaël Salaün
2025-06-26 14:49 ` Song Liu
2025-06-26 10:22 ` NeilBrown
2025-06-26 14:28 ` Song Liu
2025-06-26 22:51 ` NeilBrown
2025-06-27 0:21 ` Song Liu
2025-07-07 10:46 ` Christian Brauner
2025-07-07 11:17 ` Christian Brauner
2025-07-07 18:50 ` Song Liu
2025-07-09 16:06 ` Mickaël Salaün
2025-07-09 17:31 ` Song Liu
2025-07-09 22:24 ` NeilBrown
2025-07-09 22:50 ` Song Liu
2025-07-10 0:58 ` NeilBrown
2025-07-10 6:28 ` Song Liu
2025-07-14 21:09 ` Song Liu
2025-07-24 17:35 ` Mickaël Salaün
2025-07-26 9:52 ` Song Liu
2025-07-09 22:14 ` NeilBrown
2025-07-09 22:41 ` Song Liu
2025-07-10 0:58 ` NeilBrown
2025-07-07 10:43 ` Christian Brauner
2025-07-03 5:04 ` Song Liu
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=20250617061116.3681325-2-song@kernel.org \
--to=song@kernel.org \
--cc=andrii@kernel.org \
--cc=ast@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=brauner@kernel.org \
--cc=daniel@iogearbox.net \
--cc=eddyz87@gmail.com \
--cc=jack@suse.cz \
--cc=kernel-team@meta.com \
--cc=kpsingh@kernel.org \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-security-module@vger.kernel.org \
--cc=m@maowtm.org \
--cc=martin.lau@linux.dev \
--cc=mattbobrowski@google.com \
--cc=neil@brown.name \
--cc=viro@zeniv.linux.org.uk \
/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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.