All of lore.kernel.org
 help / color / mirror / Atom feed
From: KP Singh <kpsingh@kernel.org>
To: bpf@vger.kernel.org, linux-security-module@vger.kernel.org
Cc: bboscaccy@linux.microsoft.com, paul@paul-moore.com,
	kys@microsoft.com, ast@kernel.org, daniel@iogearbox.net,
	andrii@kernel.org, KP Singh <kpsingh@kernel.org>
Subject: [PATCH v2 08/13] bpf: Implement signature verification for BPF programs
Date: Mon, 21 Jul 2025 23:19:53 +0200	[thread overview]
Message-ID: <20250721211958.1881379-9-kpsingh@kernel.org> (raw)
In-Reply-To: <20250721211958.1881379-1-kpsingh@kernel.org>

This patch extends the BPF_PROG_LOAD command by adding three new fields
to `union bpf_attr` in the user-space API:

  - signature: A pointer to the signature blob.
  - signature_size: The size of the signature blob.
  - keyring_id: The serial number of a loaded kernel keyring (e.g.,
    the user or session keyring) containing the trusted public keys.

When a BPF program is loaded with a signature, the kernel:

1.  Retrieves the trusted keyring using the provided `keyring_id`.
2.  Verifies the supplied signature against the BPF program's
    instruction buffer.
3.  If the signature is valid and was generated by a key in the trusted
    keyring, the program load proceeds.
4.  If no signature is provided, the load proceeds as before, allowing
    for backward compatibility. LSMs can chose to restrict unsigned
    programs and implement a security policy.
5.  If signature verification fails for any reason,
    the program is not loaded.

Signed-off-by: KP Singh <kpsingh@kernel.org>
---
 crypto/asymmetric_keys/pkcs7_verify.c |  1 +
 include/linux/verification.h          |  1 +
 include/uapi/linux/bpf.h              | 10 +++++++
 kernel/bpf/helpers.c                  |  2 +-
 kernel/bpf/syscall.c                  | 41 ++++++++++++++++++++++++++-
 tools/include/uapi/linux/bpf.h        | 10 +++++++
 tools/lib/bpf/bpf.c                   |  2 +-
 7 files changed, 64 insertions(+), 3 deletions(-)

diff --git a/crypto/asymmetric_keys/pkcs7_verify.c b/crypto/asymmetric_keys/pkcs7_verify.c
index f0d4ff3c20a8..6d6475e3a9bf 100644
--- a/crypto/asymmetric_keys/pkcs7_verify.c
+++ b/crypto/asymmetric_keys/pkcs7_verify.c
@@ -429,6 +429,7 @@ int pkcs7_verify(struct pkcs7_message *pkcs7,
 		/* Authattr presence checked in parser */
 		break;
 	case VERIFYING_UNSPECIFIED_SIGNATURE:
+	case VERIFYING_BPF_SIGNATURE:
 		if (pkcs7->data_type != OID_data) {
 			pr_warn("Invalid unspecified sig (not pkcs7-data)\n");
 			return -EKEYREJECTED;
diff --git a/include/linux/verification.h b/include/linux/verification.h
index 4f3022d081c3..dec7f2beabfd 100644
--- a/include/linux/verification.h
+++ b/include/linux/verification.h
@@ -36,6 +36,7 @@ enum key_being_used_for {
 	VERIFYING_KEY_SIGNATURE,
 	VERIFYING_KEY_SELF_SIGNATURE,
 	VERIFYING_UNSPECIFIED_SIGNATURE,
+	VERIFYING_BPF_SIGNATURE,
 	NR__KEY_BEING_USED_FOR
 };
 #ifdef CONFIG_SYSTEM_DATA_VERIFICATION
diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
index fd3b895ebebf..b42c3740e053 100644
--- a/include/uapi/linux/bpf.h
+++ b/include/uapi/linux/bpf.h
@@ -1607,6 +1607,16 @@ union bpf_attr {
 		 * continuous.
 		 */
 		__u32		fd_array_cnt;
+		/* Pointer to a buffer containing the signature of the BPF
+		 * program.
+		 */
+		__aligned_u64   signature;
+		/* Size of the signature buffer in bytes. */
+		__u32 		signature_size;
+		/* ID of the kernel keyring to be used for signature
+		 * verification.
+		 */
+		__u32 		keyring_id;
 	};
 
 	struct { /* anonymous struct used by BPF_OBJ_* commands */
diff --git a/kernel/bpf/helpers.c b/kernel/bpf/helpers.c
index a052bbbcbfc5..e883c91b3633 100644
--- a/kernel/bpf/helpers.c
+++ b/kernel/bpf/helpers.c
@@ -3853,7 +3853,7 @@ __bpf_kfunc int bpf_verify_pkcs7_signature(struct bpf_dynptr *data_p,
 
 	return verify_pkcs7_signature(data, data_len, sig, sig_len,
 				      trusted_keyring->key,
-				      VERIFYING_UNSPECIFIED_SIGNATURE, NULL,
+				      VERIFYING_BPF_SIGNATURE, NULL,
 				      NULL);
 #else
 	return -EOPNOTSUPP;
diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
index 22fda92ab7ce..111f91a99166 100644
--- a/kernel/bpf/syscall.c
+++ b/kernel/bpf/syscall.c
@@ -2779,8 +2779,41 @@ static bool is_perfmon_prog_type(enum bpf_prog_type prog_type)
 	}
 }
 
+static noinline int bpf_prog_verify_signature(struct bpf_prog *prog,
+					      union bpf_attr *attr,
+					      bool is_kernel)
+{
+	bpfptr_t usig = make_bpfptr(attr->signature, is_kernel);
+	struct bpf_dynptr_kern sig_ptr, insns_ptr;
+	struct bpf_key *key = NULL;
+	void *sig;
+	int err = 0;
+
+	key = bpf_lookup_user_key(attr->keyring_id, 0);
+	if (!key)
+		return -ENOKEY;
+
+	sig = kvmemdup_bpfptr(usig, attr->signature_size);
+	if (!sig) {
+		bpf_key_put(key);
+		return -ENOMEM;
+	}
+
+	bpf_dynptr_init(&sig_ptr, sig, BPF_DYNPTR_TYPE_LOCAL, 0,
+			attr->signature_size);
+	bpf_dynptr_init(&insns_ptr, prog->insnsi, BPF_DYNPTR_TYPE_LOCAL, 0,
+			prog->len * sizeof(struct bpf_insn));
+
+	err = bpf_verify_pkcs7_signature((struct bpf_dynptr *)&insns_ptr,
+					 (struct bpf_dynptr *)&sig_ptr, key);
+
+	bpf_key_put(key);
+	kvfree(sig);
+	return err;
+}
+
 /* last field in 'union bpf_attr' used by this command */
-#define BPF_PROG_LOAD_LAST_FIELD fd_array_cnt
+#define BPF_PROG_LOAD_LAST_FIELD keyring_id
 
 static int bpf_prog_load(union bpf_attr *attr, bpfptr_t uattr, u32 uattr_size)
 {
@@ -2944,6 +2977,12 @@ static int bpf_prog_load(union bpf_attr *attr, bpfptr_t uattr, u32 uattr_size)
 	/* eBPF programs must be GPL compatible to use GPL-ed functions */
 	prog->gpl_compatible = license_is_gpl_compatible(license) ? 1 : 0;
 
+	if (attr->signature) {
+		err = bpf_prog_verify_signature(prog, attr, uattr.is_kernel);
+		if (err)
+			goto free_prog;
+	}
+
 	prog->orig_prog = NULL;
 	prog->jited = 0;
 
diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h
index fd3b895ebebf..b42c3740e053 100644
--- a/tools/include/uapi/linux/bpf.h
+++ b/tools/include/uapi/linux/bpf.h
@@ -1607,6 +1607,16 @@ union bpf_attr {
 		 * continuous.
 		 */
 		__u32		fd_array_cnt;
+		/* Pointer to a buffer containing the signature of the BPF
+		 * program.
+		 */
+		__aligned_u64   signature;
+		/* Size of the signature buffer in bytes. */
+		__u32 		signature_size;
+		/* ID of the kernel keyring to be used for signature
+		 * verification.
+		 */
+		__u32 		keyring_id;
 	};
 
 	struct { /* anonymous struct used by BPF_OBJ_* commands */
diff --git a/tools/lib/bpf/bpf.c b/tools/lib/bpf/bpf.c
index 6a08a1559237..9c7815ddd829 100644
--- a/tools/lib/bpf/bpf.c
+++ b/tools/lib/bpf/bpf.c
@@ -240,7 +240,7 @@ int bpf_prog_load(enum bpf_prog_type prog_type,
 		  const struct bpf_insn *insns, size_t insn_cnt,
 		  struct bpf_prog_load_opts *opts)
 {
-	const size_t attr_sz = offsetofend(union bpf_attr, fd_array_cnt);
+	const size_t attr_sz = offsetofend(union bpf_attr, keyring_id);
 	void *finfo = NULL, *linfo = NULL;
 	const char *func_info, *line_info;
 	__u32 log_size, log_level, attach_prog_fd, attach_btf_obj_fd;
-- 
2.43.0


  parent reply	other threads:[~2025-07-21 21:20 UTC|newest]

Thread overview: 34+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-07-21 21:19 [PATCH v2 00/13] Signed BPF programs KP Singh
2025-07-21 21:19 ` [PATCH v2 01/13] bpf: Update the bpf_prog_calc_tag to use SHA256 KP Singh
2025-07-21 21:19 ` [PATCH v2 02/13] bpf: Implement exclusive map creation KP Singh
2025-07-29 22:59   ` Fan Wu
2025-08-11 22:48     ` KP Singh
2025-07-21 21:19 ` [PATCH v2 03/13] libbpf: Implement SHA256 internal helper KP Singh
2025-07-21 21:19 ` [PATCH v2 04/13] libbpf: Support exclusive map creation KP Singh
2025-07-29  2:25   ` Alexei Starovoitov
2025-08-11 22:18     ` KP Singh
2025-07-21 21:19 ` [PATCH v2 05/13] selftests/bpf: Add tests for exclusive maps KP Singh
2025-07-21 21:19 ` [PATCH v2 06/13] bpf: Return hashes of maps in BPF_OBJ_GET_INFO_BY_FD KP Singh
2025-07-21 21:19 ` [PATCH v2 07/13] bpf: Move the signature kfuncs to helpers.c KP Singh
2025-07-23 16:47   ` James Bottomley
2025-07-21 21:19 ` KP Singh [this message]
2025-07-23 17:11   ` [PATCH v2 08/13] bpf: Implement signature verification for BPF programs James Bottomley
2025-07-24 17:22     ` KP Singh
2025-07-31 15:57   ` Dan Carpenter
2025-08-11 22:22     ` KP Singh
2025-08-05 18:28   ` Blaise Boscaccy
2025-08-13  2:20     ` Paul Moore
2025-07-21 21:19 ` [PATCH v2 09/13] libbpf: Update light skeleton for signing KP Singh
2025-07-21 21:19 ` [PATCH v2 10/13] libbpf: Embed and verify the metadata hash in the loader KP Singh
2025-07-21 21:19 ` [PATCH v2 11/13] bpftool: Add support for signing BPF programs KP Singh
2025-07-22 15:51   ` Quentin Monnet
2025-07-24 17:07     ` KP Singh
2025-08-11 14:23       ` KP Singh
2025-08-11 14:39         ` Quentin Monnet
2025-07-21 21:19 ` [PATCH v2 12/13] selftests/bpf: Enable signature verification for all lskel tests KP Singh
2025-07-29  2:27   ` Alexei Starovoitov
2025-08-11 22:20     ` KP Singh
2025-07-21 21:19 ` [PATCH v2 13/13] selftests/bpf: Add test for signed programs KP Singh
2025-07-29  2:30   ` Alexei Starovoitov
2025-08-11 14:24     ` KP Singh
  -- strict thread matches above, loose matches on Subject: below --
2025-07-23  4:40 [PATCH v2 08/13] bpf: Implement signature verification for BPF programs kernel test robot

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=20250721211958.1881379-9-kpsingh@kernel.org \
    --to=kpsingh@kernel.org \
    --cc=andrii@kernel.org \
    --cc=ast@kernel.org \
    --cc=bboscaccy@linux.microsoft.com \
    --cc=bpf@vger.kernel.org \
    --cc=daniel@iogearbox.net \
    --cc=kys@microsoft.com \
    --cc=linux-security-module@vger.kernel.org \
    --cc=paul@paul-moore.com \
    /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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.