Linux Security Modules development
 help / color / mirror / Atom feed
From: KP Singh <kpsingh@kernel.org>
To: linux-security-module@vger.kernel.org, bpf@vger.kernel.org
Cc: ast@kernel.org, daniel@iogearbox.net, memxor@gmail.com,
	James.Bottomley@HansenPartnership.com, paul@paul-moore.com,
	KP Singh <kpsingh@kernel.org>
Subject: [PATCH bpf-next 02/13] bpf: include prog BTF in the signed loader signature scope
Date: Fri, 22 May 2026 04:32:22 +0200	[thread overview]
Message-ID: <20260522023234.3778588-3-kpsingh@kernel.org> (raw)
In-Reply-To: <20260522023234.3778588-1-kpsingh@kernel.org>

bpf_prog_verify_signature hashes only prog->insnsi, so FUNC names
in prog BTF are not covered by the signature. Since we need to
support kfuncs for loader programs with prog BTF information, the
signature needs to cover BTF so that it can be trusted.

When attr->prog_btf_fd is set, build the verify dynptr over
insns || raw_btf so the signature covers both. Fall back to insns-only
otherwise so existing signed lskels keep loading. Hoist the
prog_btf_fd resolution into bpf_prog_load so the BTF is available
before signature verification.

Signed-off-by: KP Singh <kpsingh@kernel.org>
---
 include/linux/btf.h    |  1 +
 kernel/bpf/btf.c       |  8 +++++++
 kernel/bpf/check_btf.c | 18 +++-------------
 kernel/bpf/syscall.c   | 49 +++++++++++++++++++++++++++++++++++++-----
 4 files changed, 56 insertions(+), 20 deletions(-)

diff --git a/include/linux/btf.h b/include/linux/btf.h
index 48108471c5b1..ab1fe7c8df20 100644
--- a/include/linux/btf.h
+++ b/include/linux/btf.h
@@ -216,6 +216,7 @@ int btf_type_snprintf_show(const struct btf *btf, u32 type_id, void *obj,
 int btf_get_fd_by_id(u32 id);
 u32 btf_obj_id(const struct btf *btf);
 bool btf_is_kernel(const struct btf *btf);
+const void *btf_get_raw_data(const struct btf *btf, u32 *data_size);
 bool btf_is_module(const struct btf *btf);
 bool btf_is_vmlinux(const struct btf *btf);
 struct module *btf_try_get_module(const struct btf *btf);
diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c
index a62d78581207..6f1d9b3ba6a3 100644
--- a/kernel/bpf/btf.c
+++ b/kernel/bpf/btf.c
@@ -8322,11 +8322,19 @@ u32 btf_obj_id(const struct btf *btf)
 	return READ_ONCE(btf->id);
 }
 
+const void *btf_get_raw_data(const struct btf *btf, u32 *data_size)
+{
+	if (data_size)
+		*data_size = btf->data_size;
+	return btf->data;
+}
+
 bool btf_is_kernel(const struct btf *btf)
 {
 	return btf->kernel_btf;
 }
 
+
 bool btf_is_module(const struct btf *btf)
 {
 	return btf->kernel_btf && strcmp(btf->name, "vmlinux") != 0;
diff --git a/kernel/bpf/check_btf.c b/kernel/bpf/check_btf.c
index 93bebe6fe12e..c52cc859abac 100644
--- a/kernel/bpf/check_btf.c
+++ b/kernel/bpf/check_btf.c
@@ -411,28 +411,16 @@ int bpf_check_btf_info_early(struct bpf_verifier_env *env,
 			     const union bpf_attr *attr,
 			     bpfptr_t uattr)
 {
-	struct btf *btf;
-	int err;
-
 	if (!attr->func_info_cnt && !attr->line_info_cnt) {
 		if (check_abnormal_return(env))
 			return -EINVAL;
 		return 0;
 	}
 
-	btf = btf_get_by_fd(attr->prog_btf_fd);
-	if (IS_ERR(btf))
-		return PTR_ERR(btf);
-	if (btf_is_kernel(btf)) {
-		btf_put(btf);
-		return -EACCES;
-	}
-	env->prog->aux->btf = btf;
+	if (env->prog->aux->btf)
+		return check_btf_func_early(env, attr, uattr);
 
-	err = check_btf_func_early(env, attr, uattr);
-	if (err)
-		return err;
-	return 0;
+	return -EINVAL;
 }
 
 int bpf_check_btf_info(struct bpf_verifier_env *env,
diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
index 51fe8d77bb39..6d1db5eaad3c 100644
--- a/kernel/bpf/syscall.c
+++ b/kernel/bpf/syscall.c
@@ -2816,9 +2816,11 @@ static 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_dynptr_kern sig_ptr, data_ptr;
 	struct bpf_key *key = NULL;
-	void *sig;
+	u32 insns_sz, btf_sz = 0;
+	const void *btf_data = NULL;
+	void *sig, *data = NULL;
 	int err = 0;
 
 	/*
@@ -2842,14 +2844,34 @@ static int bpf_prog_verify_signature(struct bpf_prog *prog, union bpf_attr *attr
 		return PTR_ERR(sig);
 	}
 
+	insns_sz = prog->len * sizeof(struct bpf_insn);
+
+	if (prog->aux->btf)
+		btf_data = btf_get_raw_data(prog->aux->btf, &btf_sz);
+
+	if (bpf_dynptr_check_size(insns_sz + btf_sz)) {
+		err = -E2BIG;
+		goto out;
+	}
+	data = kvmalloc(insns_sz + btf_sz, GFP_KERNEL);
+	if (!data) {
+		err = -ENOMEM;
+		goto out;
+	}
+	memcpy(data, prog->insnsi, insns_sz);
+	if (btf_sz)
+		memcpy(data + insns_sz, btf_data, btf_sz);
+
+	bpf_dynptr_init(&data_ptr, data, BPF_DYNPTR_TYPE_LOCAL, 0,
+			insns_sz + btf_sz);
 	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,
+	err = bpf_verify_pkcs7_signature((struct bpf_dynptr *)&data_ptr,
 					 (struct bpf_dynptr *)&sig_ptr, key);
 
+out:
+	kvfree(data);
 	bpf_key_put(key);
 	kvfree(sig);
 	return err;
@@ -3037,6 +3059,21 @@ 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->prog_btf_fd) {
+		struct btf *btf = btf_get_by_fd(attr->prog_btf_fd);
+
+		if (IS_ERR(btf)) {
+			err = PTR_ERR(btf);
+			goto free_prog;
+		}
+		if (btf_is_kernel(btf)) {
+			btf_put(btf);
+			err = -EACCES;
+			goto free_prog;
+		}
+		prog->aux->btf = btf;
+	}
+
 	if (attr->signature) {
 		err = bpf_prog_verify_signature(prog, attr, uattr.is_kernel);
 		if (err)
@@ -3148,6 +3185,8 @@ static int bpf_prog_load(union bpf_attr *attr, bpfptr_t uattr, u32 uattr_size)
 	free_uid(prog->aux->user);
 	if (prog->aux->attach_btf)
 		btf_put(prog->aux->attach_btf);
+	if (prog->aux->btf)
+		btf_put(prog->aux->btf);
 	bpf_prog_free(prog);
 put_token:
 	bpf_token_put(token);
-- 
2.53.0


  parent reply	other threads:[~2026-05-22  2:32 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-05-22  2:32 [PATCH bpf-next 00/13] Signed BPF + IPE Policies KP Singh
2026-05-22  2:32 ` [PATCH bpf-next 01/13] bpf: expose signature verdict to LSMs via bpf_prog_aux KP Singh
2026-05-22  2:32 ` KP Singh [this message]
2026-05-22  2:32 ` [PATCH bpf-next 03/13] bpf, libbpf: load prog BTF in the skel_internal loader KP Singh
2026-05-22  2:32 ` [PATCH bpf-next 04/13] bpf: add bpf_loader_verify_metadata kfunc KP Singh
2026-05-22  2:32 ` [PATCH bpf-next 05/13] bpf: compute prog->digest at BPF_PROG_LOAD entry KP Singh
2026-05-22  2:32 ` [PATCH bpf-next 06/13] bpf: resolve loader-style kfunc CALLs against prog BTF KP Singh
2026-05-22  2:32 ` [PATCH bpf-next 07/13] libbpf: generate prog BTF for loader programs KP Singh
2026-05-22  2:32 ` [PATCH bpf-next 08/13] bpftool gen: embed loader prog BTF in the lskel header KP Singh
2026-05-22  2:32 ` [PATCH bpf-next 09/13] lsm: add bpf_prog_load_post_integrity hook KP Singh
2026-05-22  2:32 ` [PATCH bpf-next 10/13] bpf: invoke security_bpf_prog_load_post_integrity from the metadata kfunc KP Singh
2026-05-22  2:32 ` [PATCH bpf-next 11/13] ipe: add BPF program signature properties KP Singh
2026-05-22  2:32 ` [PATCH bpf-next 12/13] ipe: gate post-integrity BPF program loads KP Singh
2026-05-22  2:32 ` [PATCH bpf-next 13/13] selftests/bpf: add IPE BPF policy integration tests KP Singh

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=20260522023234.3778588-3-kpsingh@kernel.org \
    --to=kpsingh@kernel.org \
    --cc=James.Bottomley@HansenPartnership.com \
    --cc=ast@kernel.org \
    --cc=bpf@vger.kernel.org \
    --cc=daniel@iogearbox.net \
    --cc=linux-security-module@vger.kernel.org \
    --cc=memxor@gmail.com \
    --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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox