From: Justin Suess <utilityemal77@gmail.com>
To: gnoack3000@gmail.com, mic@digikod.net
Cc: linux-kernel@vger.kernel.org,
linux-security-module@vger.kernel.org,
Justin Suess <utilityemal77@gmail.com>
Subject: [PATCH v8 03/10] landlock: Use landlock_walk_path_up() in collect_domain_accesses()
Date: Thu, 28 May 2026 21:52:02 -0400 [thread overview]
Message-ID: <20260529015210.500291-4-utilityemal77@gmail.com> (raw)
In-Reply-To: <20260529015210.500291-1-utilityemal77@gmail.com>
Replace the open-coded loop with landlock_walk_path_up() and change the
function signature from (mnt_root, dir) to a single struct path. The
caller's mount point and starting dentry are now both carried in @path,
which keeps the traversal logic consistent with
is_access_to_paths_allowed().
No functional change intended.
Signed-off-by: Justin Suess <utilityemal77@gmail.com>
---
Notes:
v7..v8 changes:
* Reworded commit message.
* Changed collect_domain_accesses() to take a single struct path *
instead of separate mnt_root/dir parameters, simplifying the
interface and matching is_access_to_paths_allowed().
* Tightened the disconnected-directory stop condition to require
!d_unhashed(walker_path.dentry) when comparing against the mount
root, so disconnected bind-mount roots are not mistaken for the
real mount root.
security/landlock/fs.c | 82 ++++++++++++++++++++++--------------------
1 file changed, 44 insertions(+), 38 deletions(-)
diff --git a/security/landlock/fs.c b/security/landlock/fs.c
index 8fb0aa59e180..6552351e0b9c 100644
--- a/security/landlock/fs.c
+++ b/security/landlock/fs.c
@@ -1032,48 +1032,51 @@ static access_mask_t maybe_remove(const struct dentry *const dentry)
* collect_domain_accesses - Walk through a file path and collect accesses
*
* @domain: Domain to check against.
- * @mnt_root: Last directory to check.
- * @dir: Directory to start the walk from.
+ * @path: Path to start the walk from and whose mount root is the last
+ * directory to check.
* @layer_masks_dom: Where to store the collected accesses.
*
- * This helper is useful to begin a path walk from the @dir directory to a
- * @mnt_root directory used as a mount point. This mount point is the common
- * ancestor between the source and the destination of a renamed and linked
- * file. While walking from @dir to @mnt_root, we record all the domain's
- * allowed accesses in @layer_masks_dom.
+ * This helper is useful to begin a path walk from @path to the mount root
+ * directory used as a mount point. This mount point is the common ancestor
+ * between the source and the destination of a renamed and linked file. While
+ * walking from @path to that mount root, we record all the domain's allowed
+ * accesses in @layer_masks_dom.
*
- * Because of disconnected directories, this walk may not reach @mnt_dir. In
- * this case, the walk will continue to @mnt_dir after this call.
+ * Because of disconnected directories, this walk may not reach that mount
+ * root. In this case, the walk will continue to the mount root after this
+ * call.
*
* This is similar to is_access_to_paths_allowed() but much simpler because it
* only handles walking on the same mount point and only checks one set of
* accesses.
*
- * Return: True if all the domain access rights are allowed for @dir, false if
- * the walk reached @mnt_root.
+ * Return: True if all the domain access rights are allowed for @path, false if
+ * the walk reached the mount root.
*/
-static bool collect_domain_accesses(const struct landlock_ruleset *const domain,
- const struct dentry *const mnt_root,
- struct dentry *dir,
- struct layer_masks *layer_masks_dom)
+static bool
+collect_domain_accesses(const struct landlock_ruleset *const domain,
+ const struct path *const path,
+ struct layer_masks *layer_masks_dom)
{
bool ret = false;
+ struct path walker_path;
- if (WARN_ON_ONCE(!domain || !mnt_root || !dir || !layer_masks_dom))
+ if (WARN_ON_ONCE(!domain || !path || !path->dentry || !path->mnt ||
+ !layer_masks_dom))
return true;
- if (is_nouser_or_private(dir))
+ if (is_nouser_or_private(path->dentry))
return true;
if (!landlock_init_layer_masks(domain, LANDLOCK_MASK_ACCESS_FS,
layer_masks_dom, LANDLOCK_KEY_INODE))
return true;
- dget(dir);
+ walker_path = *path;
+ path_get(&walker_path);
while (true) {
- struct dentry *parent_dentry;
-
/* Gets all layers allowing all domain accesses. */
- if (landlock_unmask_layers(find_rule(domain, dir),
+ if (landlock_unmask_layers(find_rule(domain,
+ walker_path.dentry),
layer_masks_dom)) {
/*
* Stops when all handled accesses are allowed by at
@@ -1084,17 +1087,19 @@ static bool collect_domain_accesses(const struct landlock_ruleset *const domain,
}
/*
- * Stops at the mount point or the filesystem root for a disconnected
- * directory.
+ * Stops at the mount point or the filesystem root for a
+ * disconnected directory.
*/
- if (dir == mnt_root || unlikely(IS_ROOT(dir)))
+ if ((walker_path.dentry == path->mnt->mnt_root &&
+ walker_path.mnt == path->mnt) ||
+ unlikely(IS_ROOT(walker_path.dentry)))
break;
- parent_dentry = dget_parent(dir);
- dput(dir);
- dir = parent_dentry;
+ if (WARN_ON_ONCE(landlock_walk_path_up(&walker_path) !=
+ LANDLOCK_WALK_CONTINUE))
+ break;
}
- dput(dir);
+ path_put(&walker_path);
return ret;
}
@@ -1160,7 +1165,7 @@ static int current_check_refer_path(struct dentry *const old_dentry,
bool allow_parent1, allow_parent2;
access_mask_t access_request_parent1, access_request_parent2;
struct path mnt_dir;
- struct dentry *old_parent;
+ struct path old_parent_path;
struct layer_masks layer_masks_parent1 = {}, layer_masks_parent2 = {};
struct landlock_request request1 = {}, request2 = {};
@@ -1214,18 +1219,19 @@ static int current_check_refer_path(struct dentry *const old_dentry,
/*
* old_dentry may be the root of the common mount point and
* !IS_ROOT(old_dentry) at the same time (e.g. with open_tree() and
- * OPEN_TREE_CLONE). We do not need to call dget(old_parent) because
- * we keep a reference to old_dentry.
+ * OPEN_TREE_CLONE). We do not need to call path_get(&old_parent_path)
+ * because we keep a reference to old_dentry.
*/
- old_parent = (old_dentry == mnt_dir.dentry) ? old_dentry :
- old_dentry->d_parent;
+ old_parent_path.mnt = mnt_dir.mnt;
+ old_parent_path.dentry = (old_dentry == mnt_dir.dentry) ?
+ old_dentry :
+ old_dentry->d_parent;
/* new_dir->dentry is equal to new_dentry->d_parent */
- allow_parent1 = collect_domain_accesses(subject->domain, mnt_dir.dentry,
- old_parent,
+ allow_parent1 = collect_domain_accesses(subject->domain,
+ &old_parent_path,
&layer_masks_parent1);
- allow_parent2 = collect_domain_accesses(subject->domain, mnt_dir.dentry,
- new_dir->dentry,
+ allow_parent2 = collect_domain_accesses(subject->domain, new_dir,
&layer_masks_parent2);
if (allow_parent1 && allow_parent2)
return 0;
@@ -1244,7 +1250,7 @@ static int current_check_refer_path(struct dentry *const old_dentry,
return 0;
if (request1.access) {
- request1.audit.u.path.dentry = old_parent;
+ request1.audit.u.path.dentry = old_parent_path.dentry;
landlock_log_denial(subject, &request1);
}
if (request2.access) {
--
2.53.0
next prev parent reply other threads:[~2026-05-29 1:52 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-05-29 1:51 [PATCH v8 00/10] Implement LANDLOCK_ADD_RULE_NO_INHERIT Justin Suess
2026-05-29 1:52 ` [PATCH v8 01/10] landlock: Add landlock_walk_path_up() helper Justin Suess
2026-05-29 1:52 ` [PATCH v8 02/10] landlock: Use landlock_walk_path_up() in is_access_to_paths_allowed() Justin Suess
2026-05-29 1:52 ` Justin Suess [this message]
2026-05-29 1:52 ` [PATCH v8 04/10] landlock: Add LANDLOCK_ADD_RULE_NO_INHERIT user API Justin Suess
2026-05-29 1:52 ` [PATCH v8 05/10] landlock: Return inserted rule from landlock_insert_rule() Justin Suess
2026-05-29 1:52 ` [PATCH v8 06/10] landlock: Implement LANDLOCK_ADD_RULE_NO_INHERIT Justin Suess
2026-05-29 1:52 ` [PATCH v8 07/10] landlock: Add documentation for LANDLOCK_ADD_RULE_NO_INHERIT Justin Suess
2026-05-29 1:52 ` [PATCH v8 08/10] samples/landlock: Add LANDLOCK_ADD_RULE_NO_INHERIT to landlock-sandboxer Justin Suess
2026-05-29 1:52 ` [PATCH v8 09/10] selftests/landlock: Add selftests for LANDLOCK_ADD_RULE_NO_INHERIT Justin Suess
2026-05-29 1:52 ` [PATCH v8 10/10] landlock: Add KUnit tests " Justin Suess
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=20260529015210.500291-4-utilityemal77@gmail.com \
--to=utilityemal77@gmail.com \
--cc=gnoack3000@gmail.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-security-module@vger.kernel.org \
--cc=mic@digikod.net \
/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