From: Justin Suess <utilityemal77@gmail.com>
To: linux-security-module@vger.kernel.org, mic@digikod.net
Cc: m@maowtm.org, gnoack@google.com, gnoack3000@gmail.com,
matthieu@buffet.re, Justin Suess <utilityemal77@gmail.com>
Subject: [PATCH v9 3/9] landlock: Return inserted rule from landlock_insert_rule()
Date: Sat, 20 Jun 2026 23:52:16 -0400 [thread overview]
Message-ID: <20260621035223.2651547-4-utilityemal77@gmail.com> (raw)
In-Reply-To: <20260621035223.2651547-1-utilityemal77@gmail.com>
Change insert_rule() and landlock_insert_rule() to return the inserted
(or updated) struct landlock_rule pointer instead of an int errno.
Errors are propagated via ERR_PTR().
This gives callers a handle on the resulting rule so a subsequent change
can mutate per-layer flags on it (e.g. to mark ancestor rules created
for no-inherit topology sealing).
No functional change intended.
Signed-off-by: Justin Suess <utilityemal77@gmail.com>
---
Notes:
Changes since v8:
- Simplified error propagation with PTR_ERR_OR_ZERO() in
landlock_append_fs_rule() and landlock_append_net_rule(), replacing
the open-coded IS_ERR()/PTR_ERR() handling.
- Rebased onto mic/next (the flags parameter is now u32).
security/landlock/fs.c | 6 ++--
security/landlock/net.c | 6 ++--
security/landlock/ruleset.c | 68 ++++++++++++++++++-------------------
security/landlock/ruleset.h | 7 ++--
4 files changed, 45 insertions(+), 42 deletions(-)
diff --git a/security/landlock/fs.c b/security/landlock/fs.c
index 5b9cc450d614..fd829e06835d 100644
--- a/security/landlock/fs.c
+++ b/security/landlock/fs.c
@@ -369,7 +369,8 @@ int landlock_append_fs_rule(struct landlock_ruleset *const ruleset,
const struct path *const path,
access_mask_t access_rights, const u32 flags)
{
- int err;
+ int err = 0;
+ struct landlock_rule *rule;
struct landlock_id id = {
.type = LANDLOCK_KEY_INODE,
};
@@ -388,7 +389,8 @@ int landlock_append_fs_rule(struct landlock_ruleset *const ruleset,
if (IS_ERR(id.key.object))
return PTR_ERR(id.key.object);
mutex_lock(&ruleset->lock);
- err = landlock_insert_rule(ruleset, id, access_rights, flags);
+ rule = landlock_insert_rule(ruleset, id, access_rights, flags);
+ err = PTR_ERR_OR_ZERO(rule);
mutex_unlock(&ruleset->lock);
/*
* No need to check for an error because landlock_insert_rule()
diff --git a/security/landlock/net.c b/security/landlock/net.c
index cbff59ec3aba..88b9ffcd11fb 100644
--- a/security/landlock/net.c
+++ b/security/landlock/net.c
@@ -23,11 +23,11 @@ int landlock_append_net_rule(struct landlock_ruleset *const ruleset,
const u16 port, access_mask_t access_rights,
const u32 flags)
{
- int err;
const struct landlock_id id = {
.key.data = (__force uintptr_t)htons(port),
.type = LANDLOCK_KEY_NET_PORT,
};
+ struct landlock_rule *rule;
BUILD_BUG_ON(sizeof(port) > sizeof(id.key.data));
@@ -36,10 +36,10 @@ int landlock_append_net_rule(struct landlock_ruleset *const ruleset,
~landlock_get_net_access_mask(ruleset, 0);
mutex_lock(&ruleset->lock);
- err = landlock_insert_rule(ruleset, id, access_rights, flags);
+ rule = landlock_insert_rule(ruleset, id, access_rights, flags);
mutex_unlock(&ruleset->lock);
- return err;
+ return PTR_ERR_OR_ZERO(rule);
}
static int current_check_access_socket(struct socket *const sock,
diff --git a/security/landlock/ruleset.c b/security/landlock/ruleset.c
index 4dd09ea22c84..b8a35675bcbf 100644
--- a/security/landlock/ruleset.c
+++ b/security/landlock/ruleset.c
@@ -203,12 +203,13 @@ static void build_check_ruleset(void)
* added to @ruleset as new constraints, similarly to a boolean AND between
* access rights.
*
- * Return: 0 on success, -errno on failure.
+ * Return: A pointer to the inserted or updated rule, or an ERR_PTR on failure.
*/
-static int insert_rule(struct landlock_ruleset *const ruleset,
- const struct landlock_id id,
- const struct landlock_layer (*layers)[],
- const size_t num_layers)
+static struct landlock_rule *
+insert_rule(struct landlock_ruleset *const ruleset,
+ const struct landlock_id id,
+ const struct landlock_layer (*layers)[],
+ const size_t num_layers)
{
struct rb_node **walker_node;
struct rb_node *parent_node = NULL;
@@ -218,14 +219,14 @@ static int insert_rule(struct landlock_ruleset *const ruleset,
might_sleep();
lockdep_assert_held(&ruleset->lock);
if (WARN_ON_ONCE(!layers))
- return -ENOENT;
+ return ERR_PTR(-ENOENT);
if (is_object_pointer(id.type) && WARN_ON_ONCE(!id.key.object))
- return -ENOENT;
+ return ERR_PTR(-ENOENT);
root = get_root(ruleset, id.type);
if (IS_ERR(root))
- return PTR_ERR(root);
+ return ERR_CAST(root);
walker_node = &root->rb_node;
while (*walker_node) {
@@ -243,7 +244,7 @@ static int insert_rule(struct landlock_ruleset *const ruleset,
/* Only a single-level layer should match an existing rule. */
if (WARN_ON_ONCE(num_layers != 1))
- return -EINVAL;
+ return ERR_PTR(-EINVAL);
/* If there is a matching rule, updates it. */
if ((*layers)[0].level == 0) {
@@ -252,16 +253,16 @@ static int insert_rule(struct landlock_ruleset *const ruleset,
* landlock_add_rule(2), i.e. @ruleset is not a domain.
*/
if (WARN_ON_ONCE(this->num_layers != 1))
- return -EINVAL;
+ return ERR_PTR(-EINVAL);
if (WARN_ON_ONCE(this->layers[0].level != 0))
- return -EINVAL;
+ return ERR_PTR(-EINVAL);
this->layers[0].access |= (*layers)[0].access;
this->layers[0].flags.quiet |= (*layers)[0].flags.quiet;
- return 0;
+ return this;
}
if (WARN_ON_ONCE(this->layers[0].level == 0))
- return -EINVAL;
+ return ERR_PTR(-EINVAL);
/*
* Intersects access rights when it is a merge between a
@@ -270,23 +271,23 @@ static int insert_rule(struct landlock_ruleset *const ruleset,
new_rule = create_rule(id, &this->layers, this->num_layers,
&(*layers)[0]);
if (IS_ERR(new_rule))
- return PTR_ERR(new_rule);
+ return ERR_CAST(new_rule);
rb_replace_node(&this->node, &new_rule->node, root);
free_rule(this, id.type);
- return 0;
+ return new_rule;
}
/* There is no match for @id. */
build_check_ruleset();
if (ruleset->num_rules >= LANDLOCK_MAX_NUM_RULES)
- return -E2BIG;
+ return ERR_PTR(-E2BIG);
new_rule = create_rule(id, layers, num_layers, NULL);
if (IS_ERR(new_rule))
- return PTR_ERR(new_rule);
+ return ERR_CAST(new_rule);
rb_link_node(&new_rule->node, parent_node, walker_node);
rb_insert_color(&new_rule->node, root);
ruleset->num_rules++;
- return 0;
+ return new_rule;
}
static void build_check_layer(void)
@@ -305,9 +306,10 @@ static void build_check_layer(void)
}
/* @ruleset must be locked by the caller. */
-int landlock_insert_rule(struct landlock_ruleset *const ruleset,
- const struct landlock_id id,
- const access_mask_t access, const u32 flags)
+struct landlock_rule *
+landlock_insert_rule(struct landlock_ruleset *const ruleset,
+ const struct landlock_id id,
+ const access_mask_t access, const u32 flags)
{
struct landlock_layer layers[] = { {
.access = access,
@@ -326,9 +328,8 @@ static int merge_tree(struct landlock_ruleset *const dst,
struct landlock_ruleset *const src,
const enum landlock_key_type key_type)
{
- struct landlock_rule *walker_rule, *next_rule;
+ struct landlock_rule *walker_rule, *next_rule, *rule;
struct rb_root *src_root;
- int err = 0;
might_sleep();
lockdep_assert_held(&dst->lock);
@@ -358,11 +359,11 @@ static int merge_tree(struct landlock_ruleset *const dst,
layers[0].access = walker_rule->layers[0].access;
layers[0].flags = walker_rule->layers[0].flags;
- err = insert_rule(dst, id, &layers, ARRAY_SIZE(layers));
- if (err)
- return err;
+ rule = insert_rule(dst, id, &layers, ARRAY_SIZE(layers));
+ if (IS_ERR(rule))
+ return PTR_ERR(rule);
}
- return err;
+ return 0;
}
static int merge_ruleset(struct landlock_ruleset *const dst,
@@ -412,9 +413,8 @@ static int inherit_tree(struct landlock_ruleset *const parent,
struct landlock_ruleset *const child,
const enum landlock_key_type key_type)
{
- struct landlock_rule *walker_rule, *next_rule;
+ struct landlock_rule *walker_rule, *next_rule, *rule;
struct rb_root *parent_root;
- int err = 0;
might_sleep();
lockdep_assert_held(&parent->lock);
@@ -432,12 +432,12 @@ static int inherit_tree(struct landlock_ruleset *const parent,
.type = key_type,
};
- err = insert_rule(child, id, &walker_rule->layers,
- walker_rule->num_layers);
- if (err)
- return err;
+ rule = insert_rule(child, id, &walker_rule->layers,
+ walker_rule->num_layers);
+ if (IS_ERR(rule))
+ return PTR_ERR(rule);
}
- return err;
+ return 0;
}
static int inherit_ruleset(struct landlock_ruleset *const parent,
diff --git a/security/landlock/ruleset.h b/security/landlock/ruleset.h
index 61f3c253d5c9..c927bcb82fa3 100644
--- a/security/landlock/ruleset.h
+++ b/security/landlock/ruleset.h
@@ -217,9 +217,10 @@ void landlock_put_ruleset_deferred(struct landlock_ruleset *const ruleset);
DEFINE_FREE(landlock_put_ruleset, struct landlock_ruleset *,
if (!IS_ERR_OR_NULL(_T)) landlock_put_ruleset(_T))
-int landlock_insert_rule(struct landlock_ruleset *const ruleset,
- const struct landlock_id id,
- const access_mask_t access, const u32 flags);
+struct landlock_rule *
+landlock_insert_rule(struct landlock_ruleset *const ruleset,
+ const struct landlock_id id,
+ const access_mask_t access, const u32 flags);
struct landlock_ruleset *
landlock_merge_ruleset(struct landlock_ruleset *const parent,
--
2.54.0
next prev parent reply other threads:[~2026-06-21 3:52 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-06-21 3:52 [PATCH v9 0/9] Implement LANDLOCK_ADD_RULE_NO_INHERIT Justin Suess
2026-06-21 3:52 ` [PATCH v9 1/9] landlock: Add and use landlock_walk_path_up() helper Justin Suess
2026-06-21 3:52 ` [PATCH v9 2/9] landlock: Add LANDLOCK_ADD_RULE_NO_INHERIT user API Justin Suess
2026-06-21 3:52 ` Justin Suess [this message]
2026-06-21 3:52 ` [PATCH v9 4/9] landlock: Move log_fs_change_topology_dentry() above current_check_refer_path() Justin Suess
2026-06-21 3:52 ` [PATCH v9 5/9] landlock: Implement LANDLOCK_ADD_RULE_NO_INHERIT Justin Suess
2026-06-21 3:52 ` [PATCH v9 6/9] landlock: Add documentation for LANDLOCK_ADD_RULE_NO_INHERIT Justin Suess
2026-06-21 3:52 ` [PATCH v9 7/9] samples/landlock: Add LANDLOCK_ADD_RULE_NO_INHERIT to landlock-sandboxer Justin Suess
2026-06-21 3:52 ` [PATCH v9 8/9] selftests/landlock: Add selftests for LANDLOCK_ADD_RULE_NO_INHERIT Justin Suess
2026-06-21 3:52 ` [PATCH v9 9/9] 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=20260621035223.2651547-4-utilityemal77@gmail.com \
--to=utilityemal77@gmail.com \
--cc=gnoack3000@gmail.com \
--cc=gnoack@google.com \
--cc=linux-security-module@vger.kernel.org \
--cc=m@maowtm.org \
--cc=matthieu@buffet.re \
--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