[RFC PATCH v2 2/6] security: kap: add the LSM ID and internal headers

From: Ketan Bhardwaj

Date: Wed Oct 28 2026 - 09:38:04 EST


Reserve an LSM ID for KAP and add the declarations its files share.

The ID is the next free value in the target tree. It is provisional
and is for the LSM maintainers to confirm.

Assisted-by: Claude
Co-developed-by: HARIHARA SUDHAN. R <harisudhan@xxxxxxxxxx>
Signed-off-by: HARIHARA SUDHAN. R <harisudhan@xxxxxxxxxx>
Assisted-by: Codex
Signed-off-by: Ketan Bhardwaj <ketan@xxxxxxxxxx>
---
include/linux/kap.h | 16 ++++
include/uapi/linux/lsm.h | 1 +
security/kap/kap.h | 159 +++++++++++++++++++++++++++++++++++++++
3 files changed, 176 insertions(+)
create mode 100644 include/linux/kap.h
create mode 100644 security/kap/kap.h

diff --git a/include/linux/kap.h b/include/linux/kap.h
new file mode 100644
index 0000000..8d11d20
--- /dev/null
+++ b/include/linux/kap.h
@@ -0,0 +1,16 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _LINUX_KAP_H
+#define _LINUX_KAP_H
+
+#include <linux/types.h>
+
+#ifdef CONFIG_SECURITY_KAP
+int kap_check_namespace_flags(unsigned long flags, const char *operation);
+#else
+static inline int kap_check_namespace_flags(unsigned long flags, const char *operation)
+{
+ return 0;
+}
+#endif
+
+#endif /* _LINUX_KAP_H */
diff --git a/include/uapi/linux/lsm.h b/include/uapi/linux/lsm.h
index 938593d..7cb3d64 100644
--- a/include/uapi/linux/lsm.h
+++ b/include/uapi/linux/lsm.h
@@ -65,6 +65,7 @@ struct lsm_ctx {
#define LSM_ID_IMA 111
#define LSM_ID_EVM 112
#define LSM_ID_IPE 113
+#define LSM_ID_KAP 114

/*
* LSM_ATTR_XXX definitions identify different LSM attributes
diff --git a/security/kap/kap.h b/security/kap/kap.h
new file mode 100644
index 0000000..14cfe4d
--- /dev/null
+++ b/security/kap/kap.h
@@ -0,0 +1,159 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _SECURITY_KAP_H
+#define _SECURITY_KAP_H
+
+#include <linux/list.h>
+#include <linux/spinlock.h>
+#include <linux/types.h>
+
+#define KAP_TASK_IGROUP_NAME_LEN 64
+
+struct dentry;
+struct task_struct;
+
+enum kap_hook_kind {
+ KAP_HOOK_EXEC,
+ KAP_HOOK_FILE,
+ KAP_HOOK_SOCKET_CONNECT,
+ KAP_HOOK_CRED,
+ KAP_HOOK_IPC,
+ KAP_HOOK_NAMESPACE,
+ KAP_HOOK_DESCRIPTOR,
+ KAP_HOOK_BPF,
+ KAP_HOOK_PTRACE,
+ KAP_HOOK_PROCFS,
+ KAP_HOOK_EXECMEM,
+ KAP_HOOK_IO_URING,
+ KAP_HOOK_LAST = KAP_HOOK_IO_URING,
+};
+
+struct kap_task_state {
+ bool active;
+ u64 epoch;
+ char igroup_name[KAP_TASK_IGROUP_NAME_LEN];
+};
+
+struct kap_task_state *kap_task_state(struct task_struct *task);
+bool kap_fail_closed_kind(enum kap_hook_kind kind);
+int kap_check_current_target_why(enum kap_hook_kind kind, const char *target,
+ const char **why);
+int kap_check_current_emit(enum kap_hook_kind kind, const void *object,
+ const char *deny_reason, const char *allow_reason);
+int kap_check_current_target_emit(enum kap_hook_kind kind, const char *target,
+ const char *deny_reason, const char *allow_reason);
+void kap_emit_current_event_target(enum kap_hook_kind kind, int decision,
+ const char *reason, const char *target);
+
+/* Shared between the policy engine (igroup.c) and the control plane (kapfs.c). */
+#define KAP_MAX_NAME_LEN 63
+#define KAP_MAX_ROOT_LEN 64
+#define KAP_MAX_PREDICATE_BYTES 65536
+#define KAP_MAX_EVENTS_BYTES 65536
+/* The install document is the authority plus a few short header lines. */
+#define KAP_MAX_INSTALL_BYTES (KAP_MAX_PREDICATE_BYTES + 1024)
+
+enum kap_file_kind {
+ KAP_FILE_PROCS,
+ KAP_FILE_IGFD,
+ KAP_FILE_LINEAGE_ROOT,
+ KAP_FILE_AUTHORITY_EPOCH,
+ KAP_FILE_AUTHORITY,
+ KAP_FILE_TRANSITION,
+ KAP_FILE_MODE,
+ KAP_FILE_EVENTS,
+ KAP_FILE_EXPIRES_AT,
+ KAP_FILE_INSTALL,
+ KAP_FILE_COUNT,
+ /* Filesystem-wide, not created per igroup, so it sits past the count. */
+ KAP_FILE_DEFAULT = KAP_FILE_COUNT,
+};
+
+struct kap_igroup;
+
+struct kap_file_ctx {
+ enum kap_file_kind kind;
+ struct kap_igroup *igroup;
+};
+
+struct kap_bound_pid {
+ pid_t pid;
+ struct list_head node;
+};
+
+/*
+ * Predicates are compiled once at install, so a decision only walks an array.
+ * Patterns are interned into one pool and referenced by offset, so the whole
+ * thing is a flat allocation and a decision allocates nothing.
+ *
+ * The pool is sized to the authority document itself, so any document that is
+ * accepted can be compiled: a pattern costs strlen + 1 here and at least
+ * strlen + 2 in the document because of its surrounding quotes. Each set's
+ * patterns are laid out contiguously and walked by length, so there is no
+ * per-set entry limit either.
+ */
+struct kap_pattern_set {
+ u32 offset;
+ u32 count;
+};
+
+struct kap_compiled_authority {
+ char pool[KAP_MAX_PREDICATE_BYTES];
+ u32 pool_used;
+ struct kap_pattern_set allow[KAP_HOOK_LAST + 1];
+ struct kap_pattern_set deny[KAP_HOOK_LAST + 1];
+};
+
+struct kap_igroup {
+ char name[KAP_MAX_NAME_LEN + 1];
+ u64 epoch;
+ bool revoked;
+ bool has_sequence;
+ u64 last_sequence;
+ char lineage_root[KAP_MAX_ROOT_LEN + 1];
+ char authority[KAP_MAX_PREDICATE_BYTES];
+ size_t authority_len;
+ /* Expiry in Unix seconds, 0 for none. */
+ u64 expires_at;
+ /* Swapped wholesale on a successful install; NULL until the first one. */
+ struct kap_compiled_authority *compiled;
+ char events[KAP_MAX_EVENTS_BYTES];
+ size_t events_len;
+ struct kap_file_ctx files[KAP_FILE_COUNT];
+ struct list_head pids;
+ struct list_head node;
+ struct dentry *dentry;
+};
+
+struct kap_install_request {
+ char lineage_root[KAP_MAX_ROOT_LEN + 1];
+ u64 epoch;
+ u64 expires_at;
+ u64 sequence;
+ /* Points into the caller's buffer, which outlives this request. */
+ const char *authority;
+ bool have_root;
+ bool have_epoch;
+ bool have_expires_at;
+ bool have_transition;
+ bool have_authority;
+};
+
+extern struct list_head kap_igroups;
+extern spinlock_t kap_lock;
+extern bool kap_lsm_active;
+extern bool kap_ready;
+extern bool kap_default_closed;
+
+struct kap_igroup *kap_find_igroup_locked(const char *name);
+int kap_bind_pid_locked(struct kap_igroup *igroup, pid_t pid,
+ struct kap_bound_pid **entry);
+int kap_parse_transition_sequence(const char *payload, u64 *sequence);
+int kap_install_parse(char *payload, struct kap_install_request *req);
+int kap_authority_prepare(const char *doc, struct kap_compiled_authority **out);
+int kap_install_locked(struct kap_igroup *igroup,
+ const struct kap_install_request *req,
+ struct kap_compiled_authority **compiled);
+void kap_trim_newline(char *value);
+int kap_securityfs_init(void);
+
+#endif /* _SECURITY_KAP_H */
--
2.51.0