Thread (5 messages) flat view 5 messages, 2 authors, 1d ago
WARM1d

[PATCH bpf-next 1/2] lsm: add bpf_security_locked_down() kfunc

From: Justin Suess <hidden>
Date: 2026-08-15 11:20:48
Also in: bpf, lkml
Subsystem: security subsystem, the rest · Maintainers: Paul Moore, James Morris, "Serge E. Hallyn", Linus Torvalds

Add a new kfunc bpf_security_locked_down, which calls
security_locked_down and returns the result.

Create a new file security/lsm_kfuncs.c for LSM framework kfuncs.

Reject reasons outside (LOCKDOWN_NONE, LOCKDOWN_CONFIDENTIALITY_MAX)
with -EINVAL before dispatching the hook. Limit the kfunc to
BPF_PROG_TYPE_LSM and BPF_PROG_TYPE_SYSCALL programs, and refuse it
to programs attached to the locked_down hook itself, which would
recurse into the dispatch.

Signed-off-by: Justin Suess <redacted>
---
 security/Makefile     |  1 +
 security/lsm_kfuncs.c | 84 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 85 insertions(+)
 create mode 100644 security/lsm_kfuncs.c
diff --git a/security/Makefile b/security/Makefile
index 4601230ba442..dee8ff218548 100644
--- a/security/Makefile
+++ b/security/Makefile
@@ -12,6 +12,7 @@ obj-$(CONFIG_MMU)			+= min_addr.o
 
 # Object file lists
 obj-$(CONFIG_SECURITY)			+= security.o lsm_notifier.o lsm_init.o
+obj-$(CONFIG_BPF_SYSCALL)		+= lsm_kfuncs.o
 obj-$(CONFIG_SECURITYFS)		+= inode.o
 obj-$(CONFIG_SECURITY_SELINUX)		+= selinux/
 obj-$(CONFIG_SECURITY_SMACK)		+= smack/
diff --git a/security/lsm_kfuncs.c b/security/lsm_kfuncs.c
new file mode 100644
index 000000000000..a324e7d978ca
--- /dev/null
+++ b/security/lsm_kfuncs.c
@@ -0,0 +1,84 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * kfuncs exposing LSM interfaces to BPF programs.
+ *
+ * Copyright (C) 2026 Justin Suess
+ */
+#include <linux/bpf.h>
+#include <linux/btf.h>
+#include <linux/btf_ids.h>
+#include <linux/init.h>
+#include <linux/security.h>
+
+__bpf_kfunc_start_defs();
+
+/**
+ * bpf_security_locked_down - Call the security_locked_down() LSM hook
+ * @what: lockdown reason to query
+ *
+ * Return: 0 if @what is not locked down, -EPERM if it is, or -EINVAL if
+ * @what is outside (LOCKDOWN_NONE, LOCKDOWN_CONFIDENTIALITY_MAX).
+ */
+__bpf_kfunc int bpf_security_locked_down(enum lockdown_reason what)
+{
+	if (what <= LOCKDOWN_NONE || what >= LOCKDOWN_CONFIDENTIALITY_MAX)
+		return -EINVAL;
+	return security_locked_down(what);
+}
+
+__bpf_kfunc_end_defs();
+
+BTF_KFUNCS_START(lsm_kfunc_ids)
+BTF_ID_FLAGS(func, bpf_security_locked_down)
+BTF_KFUNCS_END(lsm_kfunc_ids)
+
+#ifdef CONFIG_BPF_LSM
+BTF_ID_LIST_SINGLE(lsm_locked_down_hook_id, func, bpf_lsm_locked_down)
+#endif
+
+static int lsm_kfunc_filter(const struct bpf_prog *prog, u32 kfunc_id)
+{
+	/* Filters run for every kfunc resolved through the hook. */
+	if (!btf_id_set8_contains(&lsm_kfunc_ids, kfunc_id))
+		return 0;
+
+	/*
+	 * Raw prog->type: keep out the rest of the shared tracing kfunc
+	 * set (incl. perf/NMI) and extension programs.
+	 */
+	switch (prog->type) {
+	case BPF_PROG_TYPE_SYSCALL:
+		return 0;
+#ifdef CONFIG_BPF_LSM
+	case BPF_PROG_TYPE_LSM:
+		/*
+		 * A locked_down program calling this kfunc would recurse.
+		 * Match on attach_btf_id: attach_func_name is not yet set
+		 * when the filter runs from check_cfg.
+		 */
+		if (prog->aux->attach_btf_id == lsm_locked_down_hook_id[0])
+			return -EACCES;
+		return 0;
+#endif
+	default:
+		return -EACCES;
+	}
+}
+
+static const struct btf_kfunc_id_set lsm_kfunc_set = {
+	.owner  = THIS_MODULE,
+	.set    = &lsm_kfunc_ids,
+	.filter = lsm_kfunc_filter,
+};
+
+static int __init lsm_kfuncs_init(void)
+{
+	int err;
+
+	err = register_btf_kfunc_id_set(BPF_PROG_TYPE_LSM, &lsm_kfunc_set);
+	err = err ?: register_btf_kfunc_id_set(BPF_PROG_TYPE_SYSCALL, &lsm_kfunc_set);
+	if (err)
+		pr_warn("lsm_kfuncs: kfunc registration failed: %d\n", err);
+	return err;
+}
+late_initcall(lsm_kfuncs_init);
-- 
2.54.0
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help