Add a tracepoint for Landlock path_beneath rule addition.  This is
useful to tie a Landlock object with a file for debug purpose.

Allocate the absolute path names when adding new rules.  This is OK
because landlock_add_rule(2) is not a performance critical code.

Here is an example of landlock_add_rule_fs traces:
  ruleset=0x000000007e3b1c4a key=inode:0xffff888004f59260 allowed=0xd dev=0:16 
ino=306 path=/usr
  ruleset=0x000000007e3b1c4a key=inode:0xffff888004f59240 allowed=0xffff 
dev=0:16 ino=346 path=/root

TODO: Use Landlock IDs instead of kernel addresses to identify Landlock
objects (e.g. inode).

Cc: Günther Noack <[email protected]>
Cc: Masami Hiramatsu <[email protected]>
Cc: Mathieu Desnoyers <[email protected]>
Cc: Steven Rostedt <[email protected]>
Cc: Tingmao Wang <[email protected]>
Signed-off-by: Mickaël Salaün <[email protected]>
---
 MAINTAINERS                     |  1 +
 include/trace/events/landlock.h | 68 +++++++++++++++++++++++++++++++++
 security/landlock/Makefile      | 11 +++++-
 security/landlock/fs.c          | 22 +++++++++++
 security/landlock/fs.h          |  3 ++
 security/landlock/trace.c       | 14 +++++++
 6 files changed, 117 insertions(+), 2 deletions(-)
 create mode 100644 include/trace/events/landlock.h
 create mode 100644 security/landlock/trace.c

diff --git a/MAINTAINERS b/MAINTAINERS
index d48dd6726fe6..f75c21a935c1 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -13393,6 +13393,7 @@ F:      Documentation/admin-guide/LSM/landlock.rst
 F:     Documentation/security/landlock.rst
 F:     Documentation/userspace-api/landlock.rst
 F:     fs/ioctl.c
+F:     include/trace/events/landlock.h
 F:     include/uapi/linux/landlock.h
 F:     samples/landlock/
 F:     security/landlock/
diff --git a/include/trace/events/landlock.h b/include/trace/events/landlock.h
new file mode 100644
index 000000000000..41e10965ba7b
--- /dev/null
+++ b/include/trace/events/landlock.h
@@ -0,0 +1,68 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright © 2025 Microsoft Corporation
+ */
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM landlock
+
+#if !defined(_TRACE_LANDLOCK_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_LANDLOCK_H
+
+#include <linux/tracepoint.h>
+
+struct landlock_rule_ref;
+struct landlock_ruleset;
+struct path;
+typedef u16 access_mask_t;
+
+TRACE_EVENT(landlock_add_rule_fs,
+
+       TP_PROTO(
+               const struct landlock_ruleset *ruleset,
+               const struct landlock_rule_ref *ref,
+               access_mask_t access_rights,
+               const struct path *path,
+               const char *pathname
+       ),
+
+       TP_ARGS(ruleset, ref, access_rights, path, pathname),
+
+       TP_STRUCT__entry(
+               __field(const struct landlock_ruleset *, ruleset)
+               __field(uintptr_t, ref_key)
+               __field(access_mask_t, allowed)
+               __field(dev_t, dev)
+               __field(ino_t, ino)
+               __string(pathname, pathname)
+       ),
+
+       TP_fast_assign(
+               __entry->ruleset = ruleset;
+               __entry->ref_key = ref->key.data;
+               __entry->allowed = access_rights;
+               __entry->dev = path->dentry->d_sb->s_dev;
+               __entry->ino = path->dentry->d_inode->i_ino;
+               __assign_str(pathname);
+       ),
+
+       /*
+        * The inode number may not be the user-visible one, but it will be the 
same
+        * used by audit.
+        */
+       TP_printk(
+               "ruleset=0x%p key=inode:0x%lx allowed=0x%x dev=%u:%u ino=%lu 
path=%s",
+               __entry->ruleset,
+               __entry->ref_key,
+               __entry->allowed,
+               MAJOR(__entry->dev),
+               MINOR(__entry->dev),
+               __entry->ino,
+               __print_untrusted_str(pathname)
+       )
+);
+
+#endif /* _TRACE_LANDLOCK_H */
+
+/* This part must be outside protection */
+#include <trace/define_trace.h>
diff --git a/security/landlock/Makefile b/security/landlock/Makefile
index 3160c2bdac1d..c19b406a6c67 100644
--- a/security/landlock/Makefile
+++ b/security/landlock/Makefile
@@ -1,7 +1,14 @@
 obj-$(CONFIG_SECURITY_LANDLOCK) := landlock.o
 
-landlock-y := setup.o syscalls.o object.o ruleset.o \
-       cred.o task.o fs.o
+landlock-y := \
+       setup.o \
+       syscalls.o \
+       object.o \
+       ruleset.o \
+       cred.o \
+       task.o \
+       fs.o \
+       trace.o
 
 landlock-$(CONFIG_INET) += net.o
 
diff --git a/security/landlock/fs.c b/security/landlock/fs.c
index 73a20a501c3c..e5d673240882 100644
--- a/security/landlock/fs.c
+++ b/security/landlock/fs.c
@@ -36,6 +36,7 @@
 #include <linux/types.h>
 #include <linux/wait_bit.h>
 #include <linux/workqueue.h>
+#include <trace/events/landlock.h>
 #include <uapi/linux/fiemap.h>
 #include <uapi/linux/landlock.h>
 
@@ -345,6 +346,27 @@ int landlock_append_fs_rule(struct landlock_ruleset *const 
ruleset,
        mutex_lock(&ruleset->lock);
        err = landlock_insert_rule(ruleset, ref, access_rights);
        mutex_unlock(&ruleset->lock);
+
+       if (!err && trace_landlock_add_rule_fs_enabled()) {
+               const char *pathname;
+               /* Does not handle deleted files. */
+               char *buffer __free(__putname) = __getname();
+
+               if (buffer) {
+                       const char *absolute_path =
+                               d_absolute_path(path, buffer, PATH_MAX);
+                       if (!IS_ERR_OR_NULL(absolute_path))
+                               pathname = absolute_path;
+                       else
+                               pathname = "<too_long>";
+               } else {
+                       /* Same format as audit_log_d_path(). */
+                       pathname = "<no_memory>";
+               }
+               trace_landlock_add_rule_fs(ruleset, &ref, access_rights, path,
+                                          pathname);
+       }
+
        /*
         * No need to check for an error because landlock_insert_rule()
         * increments the refcount for the new object if needed.
diff --git a/security/landlock/fs.h b/security/landlock/fs.h
index bf9948941f2f..60be95ebfb0b 100644
--- a/security/landlock/fs.h
+++ b/security/landlock/fs.h
@@ -11,6 +11,7 @@
 #define _SECURITY_LANDLOCK_FS_H
 
 #include <linux/build_bug.h>
+#include <linux/cleanup.h>
 #include <linux/fs.h>
 #include <linux/init.h>
 #include <linux/rcupdate.h>
@@ -128,4 +129,6 @@ int landlock_append_fs_rule(struct landlock_ruleset *const 
ruleset,
                            const struct path *const path,
                            access_mask_t access_hierarchy);
 
+DEFINE_FREE(__putname, char *, if (_T) __putname(_T))
+
 #endif /* _SECURITY_LANDLOCK_FS_H */
diff --git a/security/landlock/trace.c b/security/landlock/trace.c
new file mode 100644
index 000000000000..98874cda473b
--- /dev/null
+++ b/security/landlock/trace.c
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Landlock - Tracepoints
+ *
+ * Copyright © 2025 Microsoft Corporation
+ */
+
+#include <linux/path.h>
+
+#include "access.h"
+#include "ruleset.h"
+
+#define CREATE_TRACE_POINTS
+#include <trace/events/landlock.h>
-- 
2.49.0


Reply via email to