From: Justin Suess <utilityemal77@gmail.com>
To: linux-security-module@vger.kernel.org,
"Mickaël Salaün" <mic@digikod.net>
Cc: "Günther Noack" <gnoack@google.com>,
"Tingmao Wang" <m@maowtm.org>,
"Justin Suess" <utilityemal77@gmail.com>
Subject: [PATCH 2/2] landlock: Remove collect_domain_accesses
Date: Wed, 18 Feb 2026 15:18:57 -0500 [thread overview]
Message-ID: <20260218201857.1194667-3-utilityemal77@gmail.com> (raw)
In-Reply-To: <20260218201857.1194667-1-utilityemal77@gmail.com>
Remove collect_domain_accesses and replace with inline logic using the
new path walk helper in the check_current_refer_path.
Signed-off-by: Justin Suess <utilityemal77@gmail.com>
---
security/landlock/fs.c | 128 +++++++++++++++--------------------------
1 file changed, 46 insertions(+), 82 deletions(-)
diff --git a/security/landlock/fs.c b/security/landlock/fs.c
index c6ff686c9cde..efc65dc41c0d 100644
--- a/security/landlock/fs.c
+++ b/security/landlock/fs.c
@@ -1013,77 +1013,6 @@ static access_mask_t maybe_remove(const struct dentry *const dentry)
LANDLOCK_ACCESS_FS_REMOVE_FILE;
}
-/**
- * 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.
- * @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.
- *
- * Because of disconnected directories, this walk may not reach @mnt_dir. In
- * this case, the walk will continue to @mnt_dir 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.
- *
- * Returns:
- * - true if all the domain access rights are allowed for @dir;
- * - false if the walk reached @mnt_root.
- */
-static bool collect_domain_accesses(const struct landlock_ruleset *const domain,
- const struct dentry *const mnt_root,
- struct dentry *dir,
- struct layer_access_masks *layer_masks_dom)
-{
- bool ret = false;
-
- if (WARN_ON_ONCE(!domain || !mnt_root || !dir || !layer_masks_dom))
- return true;
- if (is_nouser_or_private(dir))
- return true;
-
- if (!landlock_init_layer_masks(domain, LANDLOCK_MASK_ACCESS_FS,
- layer_masks_dom, LANDLOCK_KEY_INODE))
- return true;
-
- dget(dir);
- while (true) {
- struct dentry *parent_dentry;
-
- /* Gets all layers allowing all domain accesses. */
- if (landlock_unmask_layers(find_rule(domain, dir),
- layer_masks_dom)) {
- /*
- * Stops when all handled accesses are allowed by at
- * least one rule in each layer.
- */
- ret = true;
- break;
- }
-
- /*
- * Stops at the mount point or the filesystem root for a disconnected
- * directory.
- */
- if (dir == mnt_root || unlikely(IS_ROOT(dir)))
- break;
-
- parent_dentry = dget_parent(dir);
- dput(dir);
- dir = parent_dentry;
- }
- dput(dir);
- return ret;
-}
-
/**
* current_check_refer_path - Check if a rename or link action is allowed
*
@@ -1147,7 +1076,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_access_masks layer_masks_parent1 = {},
layer_masks_parent2 = {};
struct landlock_request request1 = {}, request2 = {};
@@ -1202,20 +1131,55 @@ 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
+ * OPEN_TREE_CLONE). We do not need to 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 = unlikely(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,
- &layer_masks_parent1);
- allow_parent2 = collect_domain_accesses(subject->domain, mnt_dir.dentry,
- new_dir->dentry,
- &layer_masks_parent2);
+ allow_parent1 = false;
+ allow_parent2 = false;
+ for (size_t i = 0; i < 2; i++) {
+ const struct path *const parent_path = i ? new_dir :
+ &old_parent_path;
+ struct layer_access_masks *const layer_masks =
+ i ? &layer_masks_parent2 : &layer_masks_parent1;
+ bool *const allow_parent = i ? &allow_parent2 : &allow_parent1;
+
+ if (is_nouser_or_private(parent_path->dentry) ||
+ !landlock_init_layer_masks(
+ subject->domain, LANDLOCK_MASK_ACCESS_FS,
+ layer_masks, LANDLOCK_KEY_INODE)) {
+ *allow_parent = true;
+ continue;
+ }
+ {
+ struct path walker = *parent_path;
+
+ path_get(&walker);
+ do {
+ /* Gets all layers allowing all domain accesses. */
+ if (landlock_unmask_layers(
+ find_rule(subject->domain,
+ walker.dentry),
+ layer_masks)) {
+ /*
+ * Stops when all handled accesses are
+ * allowed by at least one rule in each
+ * layer.
+ */
+ *allow_parent = true;
+ break;
+ }
+ } while (landlock_walk_path_up(&walker) ==
+ LANDLOCK_WALK_CONTINUE);
+ path_put(&walker);
+ }
+ }
if (allow_parent1 && allow_parent2)
return 0;
@@ -1233,7 +1197,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.51.0
prev parent reply other threads:[~2026-02-18 20:19 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-02-18 20:18 [PATCH 0/2] landlock: Simplify path walk logic Justin Suess
2026-02-18 20:18 ` [PATCH 1/2] landlock: Add path walk helper Justin Suess
2026-02-18 20:18 ` Justin Suess [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=20260218201857.1194667-3-utilityemal77@gmail.com \
--to=utilityemal77@gmail.com \
--cc=gnoack@google.com \
--cc=linux-security-module@vger.kernel.org \
--cc=m@maowtm.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