[PATCH bpf-next 1/2] lsm: add bpf_security_locked_down() kfunc
Justin Suess
utilityemal77 at gmail.com
Sat Aug 15 11:20:40 UTC 2026
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 <utilityemal77 at gmail.com>
---
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
More information about the Linux-security-module-archive
mailing list