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 06/13] bpf: resolve loader-style kfunc CALLs against prog BTF
Date: Fri, 22 May 2026 04:32:26 +0200	[thread overview]
Message-ID: <20260522023234.3778588-7-kpsingh@kernel.org> (raw)
In-Reply-To: <20260522023234.3778588-1-kpsingh@kernel.org>

gen_loader-emitted signed loaders cannot bake vmlinux BTF ids into
kfunc CALL imm at sign time. Add a new pseudo
BPF_PSEUDO_KFUNC_CALL_PROG_BTF that gen_loader emits in src_reg, with
imm holding the FUNC type id in the loader's own prog BTF.

In add_subprog_and_kfunc, look the FUNC up by name in vmlinux BTF,
patch imm with the resolved id, and rewrite src_reg back to
BPF_PSEUDO_KFUNC_CALL so downstream passes see a normal kfunc CALL.
Leave standard src_reg calls unchanged.

Signed-off-by: KP Singh <kpsingh@kernel.org>
---
 include/linux/bpf_verifier.h   |  6 ++++
 include/uapi/linux/bpf.h       |  5 ++++
 kernel/bpf/verifier.c          | 54 ++++++++++++++++++++++++++++++++--
 tools/include/uapi/linux/bpf.h |  5 ++++
 4 files changed, 67 insertions(+), 3 deletions(-)

diff --git a/include/linux/bpf_verifier.h b/include/linux/bpf_verifier.h
index 185b2aa43a42..396b85830996 100644
--- a/include/linux/bpf_verifier.h
+++ b/include/linux/bpf_verifier.h
@@ -959,6 +959,12 @@ static inline bool bpf_pseudo_kfunc_call(const struct bpf_insn *insn)
 	       insn->src_reg == BPF_PSEUDO_KFUNC_CALL;
 }
 
+static inline bool bpf_pseudo_kfunc_call_prog_btf(const struct bpf_insn *insn)
+{
+	return insn->code == (BPF_JMP | BPF_CALL) &&
+	       insn->src_reg == BPF_PSEUDO_KFUNC_CALL_PROG_BTF;
+}
+
 __printf(2, 0) void bpf_verifier_vlog(struct bpf_verifier_log *log,
 				      const char *fmt, va_list args);
 __printf(2, 3) void bpf_verifier_log_write(struct bpf_verifier_env *env,
diff --git a/include/uapi/linux/bpf.h b/include/uapi/linux/bpf.h
index 552bc5d9afbd..06056e714e8e 100644
--- a/include/uapi/linux/bpf.h
+++ b/include/uapi/linux/bpf.h
@@ -1382,6 +1382,11 @@ enum {
  * bpf_call->imm == btf_id of a BTF_KIND_FUNC in the running kernel
  */
 #define BPF_PSEUDO_KFUNC_CALL	2
+/* when bpf_call->src_reg == BPF_PSEUDO_KFUNC_CALL_PROG_BTF,
+ * bpf_call->imm == btf_id of a BTF_KIND_FUNC in the program's
+ * prog BTF. The verifier resolves it to a vmlinux btf_id by name.
+ */
+#define BPF_PSEUDO_KFUNC_CALL_PROG_BTF	3
 
 enum bpf_addr_space_cast {
 	BPF_ADDR_SPACE_CAST = 1,
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index f0e45cfa5b34..1b5d06b9d74a 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -3088,6 +3088,47 @@ bool bpf_prog_has_kfunc_call(const struct bpf_prog *prog)
 	return !!prog->aux->kfunc_tab;
 }
 
+/*
+ * Resolve a gen_loader-emitted kfunc CALL by FUNC name in vmlinux BTF,
+ * then rewrite src_reg back to BPF_PSEUDO_KFUNC_CALL. Caller must have
+ * already filtered for BPF_PSEUDO_KFUNC_CALL_PROG_BTF.
+ */
+static int resolve_loader_kfunc(struct bpf_verifier_env *env,
+				struct bpf_insn *insn, int insn_idx)
+{
+	struct btf *prog_btf = env->prog->aux->btf;
+	const struct btf_type *t;
+	const char *name;
+	s32 vmlinux_id;
+
+	if (!prog_btf || !btf_vmlinux || insn->off) {
+		verbose(env, "kfunc call insn %d: PROG_BTF resolution requires prog BTF and insn->off == 0\n",
+			insn_idx);
+		return -EINVAL;
+	}
+	t = btf_type_by_id(prog_btf, insn->imm);
+	if (!t || !btf_type_is_func(t)) {
+		verbose(env, "kfunc call insn %d: imm %d is not a FUNC in prog BTF\n",
+			insn_idx, insn->imm);
+		return -EINVAL;
+	}
+	name = btf_name_by_offset(prog_btf, t->name_off);
+	if (!name || !name[0]) {
+		verbose(env, "kfunc call insn %d: prog-BTF FUNC has no name\n",
+			insn_idx);
+		return -EINVAL;
+	}
+	vmlinux_id = btf_find_by_name_kind(btf_vmlinux, name, BTF_KIND_FUNC);
+	if (vmlinux_id < 0) {
+		verbose(env, "kfunc call insn %d: %s not found in vmlinux BTF\n",
+			insn_idx, name);
+		return vmlinux_id;
+	}
+	insn->imm = vmlinux_id;
+	insn->src_reg = BPF_PSEUDO_KFUNC_CALL;
+	return 0;
+}
+
 static int add_subprog_and_kfunc(struct bpf_verifier_env *env)
 {
 	struct bpf_subprog_info *subprog = env->subprog_info;
@@ -3101,7 +3142,8 @@ static int add_subprog_and_kfunc(struct bpf_verifier_env *env)
 
 	for (i = 0; i < insn_cnt; i++, insn++) {
 		if (!bpf_pseudo_func(insn) && !bpf_pseudo_call(insn) &&
-		    !bpf_pseudo_kfunc_call(insn))
+		    !bpf_pseudo_kfunc_call(insn) &&
+		    !bpf_pseudo_kfunc_call_prog_btf(insn))
 			continue;
 
 		if (!env->bpf_capable) {
@@ -3109,10 +3151,16 @@ static int add_subprog_and_kfunc(struct bpf_verifier_env *env)
 			return -EPERM;
 		}
 
-		if (bpf_pseudo_func(insn) || bpf_pseudo_call(insn))
+		if (bpf_pseudo_func(insn) || bpf_pseudo_call(insn)) {
 			ret = add_subprog(env, i + insn->imm + 1);
-		else
+		} else {
+			if (bpf_pseudo_kfunc_call_prog_btf(insn)) {
+				ret = resolve_loader_kfunc(env, insn, i);
+				if (ret < 0)
+					return ret;
+			}
 			ret = bpf_add_kfunc_call(env, insn->imm, insn->off);
+		}
 
 		if (ret < 0)
 			return ret;
diff --git a/tools/include/uapi/linux/bpf.h b/tools/include/uapi/linux/bpf.h
index 677be9a47347..d4f7f3e0aaa3 100644
--- a/tools/include/uapi/linux/bpf.h
+++ b/tools/include/uapi/linux/bpf.h
@@ -1382,6 +1382,11 @@ enum {
  * bpf_call->imm == btf_id of a BTF_KIND_FUNC in the running kernel
  */
 #define BPF_PSEUDO_KFUNC_CALL	2
+/* when bpf_call->src_reg == BPF_PSEUDO_KFUNC_CALL_PROG_BTF,
+ * bpf_call->imm == btf_id of a BTF_KIND_FUNC in the program's
+ * prog BTF. The verifier resolves it to a vmlinux btf_id by name.
+ */
+#define BPF_PSEUDO_KFUNC_CALL_PROG_BTF	3
 
 enum bpf_addr_space_cast {
 	BPF_ADDR_SPACE_CAST = 1,
-- 
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 ` [PATCH bpf-next 02/13] bpf: include prog BTF in the signed loader signature scope KP Singh
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 ` KP Singh [this message]
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-7-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