[RFC PATCH 05/20] landlock: Make ruleset deferred free RCU safe

Justin Suess
2026-04-07T20:02:20Z

Use INIT_RCU_WORK in the landlock deferred free function, ensuring that
deferred ruleset freeing is also RCU safe.

This is important for future consumers who may free a Landlock ruleset
under RCU in subsequent patches.

Signed-off-by: Justin Suess <utilityemal77@gmail.com>
---
security/landlock/ruleset.c | 9 +++++----
security/landlock/ruleset.h | 6 +++---
2 files changed, 8 insertions(+), 7 deletions(-)

diff --git a/security/landlock/ruleset.c b/security/landlock/ruleset.c
index 4f0305796165..5845cdc58d0d 100644
--- a/security/landlock/ruleset.c
+++ b/security/landlock/ruleset.c
@@ -699,16 +699,17 @@ static void free_ruleset_work(struct work_struct *const work)
{
struct landlock_ruleset *ruleset;

- ruleset = container_of(work, struct landlock_ruleset, work_free);
+ ruleset = container_of(to_rcu_work(work), struct landlock_ruleset,
+ work_free);
free_ruleset(ruleset);
}

-/* Only called by hook_cred_free(). */
+/* Called by deferred ruleset owners that cannot free from their context. */
void landlock_put_ruleset_deferred(struct landlock_ruleset *const ruleset)
{
if (ruleset && refcount_dec_and_test(&ruleset->usage)) {
- INIT_WORK(&ruleset->work_free, free_ruleset_work);
- schedule_work(&ruleset->work_free);
+ INIT_RCU_WORK(&ruleset->work_free, free_ruleset_work);
+ queue_rcu_work(system_wq, &ruleset->work_free);
}
}

diff --git a/security/landlock/ruleset.h b/security/landlock/ruleset.h
index 0facc5cb6555..fbbd1b73476e 100644
--- a/security/landlock/ruleset.h
+++ b/security/landlock/ruleset.h
@@ -146,13 +146,13 @@ struct landlock_ruleset {
struct landlock_hierarchy *hierarchy;
union {
/**
- * @work_free: Enables to free a ruleset within a lockless
- * section. This is only used by
+ * @work_free: Enables to free a ruleset after an RCU grace
+ * period from a sleepable context. This is only used by
* landlock_put_ruleset_deferred() when @usage reaches zero.
* The fields @lock, @usage, @num_rules, @num_layers and
* @access_masks are then unused.
*/
- struct work_struct work_free;
+ struct rcu_work work_free;
struct {
/**
* @lock: Protects against concurrent modifications of
--
2.53.0