Linux Security Modules development
 help / color / mirror / Atom feed
From: Paul Moore <paul@paul-moore.com>
To: linux-security-module@vger.kernel.org
Cc: wufan@kernel.org, bboscaccy@linux.microsoft.com
Subject: [RFC PATCH] ipe: support multiple BPF integrity verification LSMs
Date: Sat, 23 May 2026 16:09:00 -0400	[thread overview]
Message-ID: <20260523200859.13527-2-paul@paul-moore.com> (raw)

Currently IPE always records the last BPF integrity verification verdict,
which is reasonable with only a single BPF verification LSM, but it
becomes problematic when multiple mechanisms end up submitting BPF
program integrity verdicts.

This patch updates IPE to record all of the received BPF program
integrity verdicts, along with their associated LSM IDs, ultimately using
the "worst" verdict in the policy enforcement engine.  Policy support for
selecting individual integrity verdicts was intentionally omitted from
this patch to keep things simple both from a code and policy developer
perspective, however future work to add selector support should be
trivial.

Signed-off-by: Paul Moore <paul@paul-moore.com>
---
 include/linux/security.h | 14 +++++++-------
 security/ipe/eval.h      |  7 ++++++-
 security/ipe/hooks.c     | 20 +++++++++++++++++---
 3 files changed, 30 insertions(+), 11 deletions(-)

diff --git a/include/linux/security.h b/include/linux/security.h
index 598cd2eb1dcd..6a987a0347a0 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -103,13 +103,13 @@ enum lsm_integrity_type {
 
 enum lsm_integrity_verdict {
 	LSM_INT_VERDICT_NONE = 0,
-	LSM_INT_VERDICT_OK,
-	LSM_INT_VERDICT_UNSIGNED,
-	LSM_INT_VERDICT_PARTIALSIG,
-	LSM_INT_VERDICT_UNKNOWNKEY,
-	LSM_INT_VERDICT_UNEXPECTED,
-	LSM_INT_VERDICT_FAULT,
-	LSM_INT_VERDICT_BADSIG,
+	LSM_INT_VERDICT_OK = 1,
+	LSM_INT_VERDICT_UNSIGNED = 2,
+	LSM_INT_VERDICT_PARTIALSIG = 3,
+	LSM_INT_VERDICT_UNKNOWNKEY = 4,
+	LSM_INT_VERDICT_UNEXPECTED = 5,
+	LSM_INT_VERDICT_FAULT = 6,
+	LSM_INT_VERDICT_BADSIG = 7,
 };
 
 /*
diff --git a/security/ipe/eval.h b/security/ipe/eval.h
index b061cb5ade27..90c7b66b9ca8 100644
--- a/security/ipe/eval.h
+++ b/security/ipe/eval.h
@@ -8,6 +8,7 @@
 
 #include <linux/file.h>
 #include <linux/types.h>
+#include <linux/lsm_count.h>
 
 #include "policy.h"
 #include "hooks.h"
@@ -39,7 +40,11 @@ struct ipe_inode {
 
 #ifdef CONFIG_IPE_PROP_BPF_SIGNATURE
 struct ipe_bpf_prog {
-	enum lsm_integrity_verdict verdict;
+	struct {
+		const struct lsm_id *lsmid;
+		enum lsm_integrity_verdict verdict;
+	} verdicts[MAX_LSM_COUNT];
+	unsigned int count;
 };
 #endif /* CONFIG_IPE_PROP_BPF_SIGNATURE */
 
diff --git a/security/ipe/hooks.c b/security/ipe/hooks.c
index 9271e129a2cf..143bb2ae2b12 100644
--- a/security/ipe/hooks.c
+++ b/security/ipe/hooks.c
@@ -9,6 +9,7 @@
 #include <linux/binfmts.h>
 #include <linux/mman.h>
 #include <linux/blk_types.h>
+#include <linux/lsm_count.h>
 
 #include "ipe.h"
 #include "hooks.h"
@@ -355,7 +356,8 @@ int ipe_inode_setintegrity(const struct inode *inode,
  * so that ipe_bpf_prog_load() can later read it for policy evaluation.
  *
  * Return:
- * * %0		- Always succeeds (policy is evaluated in bpf_prog_load)
+ * * %0		- Recorded the verdict (policy is evaluated in bpf_prog_load)
+ * * %-ENOMEM	- Exhausted room for recording verdicts
  */
 int ipe_bpf_prog_load_post_integrity(struct bpf_prog *prog,
 				     union bpf_attr *attr,
@@ -365,8 +367,14 @@ int ipe_bpf_prog_load_post_integrity(struct bpf_prog *prog,
 				     enum lsm_integrity_verdict verdict)
 {
 	struct ipe_bpf_prog *blob = ipe_bpf_prog(prog);
+	unsigned int count = blob->count;
 
-	blob->verdict = verdict;
+	if (count == MAX_LSM_COUNT)
+		return -ENOMEM;
+
+	blob->verdicts[count].lsmid = lsmid;
+	blob->verdicts[count].verdict = verdict;
+	blob->count++;
 
 	return 0;
 }
@@ -391,12 +399,18 @@ int ipe_bpf_prog_load(struct bpf_prog *prog,
 		      struct bpf_token *token,
 		      bool kernel)
 {
+	unsigned int iter;
 	struct ipe_bpf_prog *blob = ipe_bpf_prog(prog);
 	struct ipe_eval_ctx ctx = IPE_EVAL_CTX_INIT;
 
 	ctx.op = IPE_OP_BPF_PROG_LOAD;
 	ctx.hook = IPE_HOOK_BPF_PROG_LOAD;
-	ctx.bpf_verdict = blob->verdict;
+	ctx.bpf_verdict = LSM_INT_VERDICT_NONE;
+	for (iter = 0; iter < blob->count; iter++) {
+		/* pick the "wosrt" verdict */
+		if (blob->verdicts[iter].verdict > ctx.bpf_verdict)
+			ctx.bpf_verdict = blob->verdicts[iter].verdict;
+	}
 	ctx.bpf_keyring_id = attr->keyring_id;
 	ctx.bpf_kernel = kernel;
 
-- 
2.54.0


             reply	other threads:[~2026-05-23 20:09 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-05-23 20:09 Paul Moore [this message]
2026-05-23 23:05 ` [RFC PATCH] ipe: support multiple BPF integrity verification LSMs Paul Moore
2026-05-24  0:39 ` Fan Wu

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260523200859.13527-2-paul@paul-moore.com \
    --to=paul@paul-moore.com \
    --cc=bboscaccy@linux.microsoft.com \
    --cc=linux-security-module@vger.kernel.org \
    --cc=wufan@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox