[RFC PATCH 01/10] landlock: Add some debug output
Tingmao Wang
m at maowtm.org
Wed May 21 19:31:57 UTC 2025
They are behind #ifdef DEBUG for now as iterating over all the rules /
each access bits might make it slower (even if dynamic pr_debug makes the
print itself nop).
Signed-off-by: Tingmao Wang <m at maowtm.org>
---
security/landlock/fs.c | 47 ++++++++++++++++++++++++++++++++++++
security/landlock/fs.h | 1 +
security/landlock/syscalls.c | 26 ++++++++++++++++++++
3 files changed, 74 insertions(+)
diff --git a/security/landlock/fs.c b/security/landlock/fs.c
index 6fee7c20f64d..b407c644ac65 100644
--- a/security/landlock/fs.c
+++ b/security/landlock/fs.c
@@ -772,6 +772,10 @@ static bool is_access_to_paths_allowed(
layer_mask_t(*layer_masks_child1)[LANDLOCK_NUM_ACCESS_FS] = NULL,
(*layer_masks_child2)[LANDLOCK_NUM_ACCESS_FS] = NULL;
+#ifdef DEBUG
+ layer_mask_t all_layers = (1 << domain->num_layers) - 1;
+#endif
+
if (!access_request_parent1 && !access_request_parent2)
return true;
@@ -800,6 +804,14 @@ static bool is_access_to_paths_allowed(
access_masked_parent1 = access_masked_parent2 =
landlock_union_access_masks(domain).fs;
is_dom_check = true;
+
+#ifdef DEBUG
+ pr_debug(
+ "check access to path %pd4 for access request p1 %x p2 %x:\n",
+ path->dentry, access_request_parent1,
+ access_request_parent2);
+#endif
+
} else {
if (WARN_ON_ONCE(dentry_child1 || dentry_child2))
return false;
@@ -807,7 +819,15 @@ static bool is_access_to_paths_allowed(
access_masked_parent1 = access_request_parent1;
access_masked_parent2 = access_request_parent2;
is_dom_check = false;
+
+#ifdef DEBUG
+ pr_debug("check access to path %pd4 for access request %x:\n",
+ path->dentry, access_request_parent1);
+#endif
}
+#ifdef DEBUG
+ pr_debug(" (need layer mask %x)", all_layers);
+#endif
if (unlikely(dentry_child1)) {
landlock_unmask_layers(
@@ -892,6 +912,33 @@ static bool is_access_to_paths_allowed(
layer_masks_parent2,
ARRAY_SIZE(*layer_masks_parent2));
+#ifdef DEBUG
+ {
+ rcu_read_lock();
+ pr_debug(" %pd: ino %lu (%p), rule: %s, allow: %s\n",
+ walker_path.dentry,
+ walker_path.dentry->d_inode->i_ino,
+ walker_path.dentry->d_inode,
+ rule ? "exists" : "does not exist",
+ allowed_parent1 ? "yes" : "no");
+ unsigned long access_masked = access_masked_parent1;
+ unsigned long access_bit;
+ if (rule) {
+ for_each_set_bit(
+ access_bit, &access_masked,
+ ARRAY_SIZE(*layer_masks_parent1)) {
+ pr_debug(
+ " access %x allowed by layer mask %d\n",
+ (1 << access_bit),
+ (~(*layer_masks_parent1)
+ [access_bit]) &
+ all_layers);
+ }
+ }
+ rcu_read_unlock();
+ }
+#endif
+
/* Stops when a rule from each layer grants access. */
if (allowed_parent1 && allowed_parent2)
break;
diff --git a/security/landlock/fs.h b/security/landlock/fs.h
index bf9948941f2f..bedf61c15cd4 100644
--- a/security/landlock/fs.h
+++ b/security/landlock/fs.h
@@ -15,6 +15,7 @@
#include <linux/init.h>
#include <linux/rcupdate.h>
+#include "common.h"
#include "access.h"
#include "cred.h"
#include "ruleset.h"
diff --git a/security/landlock/syscalls.c b/security/landlock/syscalls.c
index 33eafb71e4f3..38eb8287f73d 100644
--- a/security/landlock/syscalls.c
+++ b/security/landlock/syscalls.c
@@ -559,6 +559,32 @@ SYSCALL_DEFINE2(landlock_restrict_self, const int, ruleset_fd, const __u32,
new_dom->hierarchy->log_status = LANDLOCK_LOG_DISABLED;
#endif /* CONFIG_AUDIT */
+#ifdef DEBUG
+ pr_debug("%s[%d] restricting self with landlock\n", current->comm,
+ current->pid);
+ struct rb_node *node;
+ pr_debug("inode tree:\n");
+ for (node = rb_first(&new_dom->root_inode); node;
+ node = rb_next(node)) {
+ const struct landlock_rule *rule =
+ rb_entry(node, struct landlock_rule, node);
+ spinlock_t *lock = &rule->key.object->lock;
+ rcu_read_lock();
+ spin_lock(lock);
+ struct inode *inode = rule->key.object->underobj;
+ if (inode)
+ pr_debug(" rule: ino %lu (%p)\n", inode->i_ino, inode);
+ else
+ pr_debug(" rule: inode released\n");
+ for (size_t i = 0; i < rule->num_layers; i++) {
+ pr_debug(" layer %u: access %x\n",
+ rule->layers[i].level, rule->layers[i].access);
+ }
+ spin_unlock(lock);
+ rcu_read_unlock();
+ }
+#endif /* DEBUG */
+
/* Replaces the old (prepared) domain. */
landlock_put_ruleset(new_llcred->domain);
new_llcred->domain = new_dom;
--
2.49.0
More information about the Linux-security-module-archive
mailing list