BPF List
 help / color / mirror / Atom feed
From: Amery Hung <ameryhung@gmail.com>
To: bpf@vger.kernel.org
Cc: alexei.starovoitov@gmail.com, andrii@kernel.org,
	daniel@iogearbox.net, eddyz87@gmail.com, memxor@gmail.com,
	ameryhung@gmail.com, kernel-team@meta.com
Subject: [PATCH bpf-next v1 12/12] bpf: Check all subprog arguments in the common path
Date: Fri, 25 Sep 2026 14:12:56 -0700	[thread overview]
Message-ID: <20260925211256.1834061-13-ameryhung@gmail.com> (raw)
In-Reply-To: <20260925211256.1834061-1-ameryhung@gmail.com>

All supported BPF-subprogram argument types now pass through
check_func_arg() from one guarded branch in the legacy validation loop.
Replace that loop and its outgoing-stack validation with
check_func_args().

The scratch prototype is indexed by BTF parameter and the call metadata
carries the BTF function prototype. The existing BTF argument iteration
therefore maps parameters to ABI slots for both kfunc and BPF subprogram
calls, including additional slots occupied by by-value aggregates.

The common checker can return non-EFAULT errors other than -EINVAL, as
the existing BTF-ID path already did. This is compatible with subprog
call handling: only -EFAULT is fatal. Any other error marks BTF
unreliable. Static subprogs can then fall back to inline verification,
while global subprogs reject the call.

Remove the caller-register plumbing that the dedicated loop required.

Signed-off-by: Amery Hung <ameryhung@gmail.com>
---
 kernel/bpf/verifier.c | 62 +++++++------------------------------------
 1 file changed, 10 insertions(+), 52 deletions(-)

diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index 97c125850c7a..d6a94dc5e644 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -10846,16 +10846,13 @@ static void gen_subprog_arg_proto(const struct bpf_subprog_info *sub, const stru
 	}
 }
 
-static int btf_check_func_arg_match(struct bpf_verifier_env *env, int subprog,
-				    struct btf *btf, struct bpf_reg_state *regs,
+static int btf_check_func_arg_match(struct bpf_verifier_env *env, int subprog, struct btf *btf,
 				    struct bpf_call_arg_meta *meta)
 {
 	struct bpf_subprog_info *sub = subprog_info(env, subprog);
 	struct bpf_func_state *caller = cur_func(env);
-	const struct btf_param *args, *stack_args;
 	const struct btf_type *func, *func_proto;
 	struct bpf_func_proto *fn;
-	u32 arg, slot, nslots;
 	int ret, err;
 
 	memset(meta, 0, sizeof(*meta));
@@ -10877,63 +10874,24 @@ static int btf_check_func_arg_match(struct bpf_verifier_env *env, int subprog,
 
 	func = btf_type_by_id(btf, env->prog->aux->func_info[subprog].type_id);
 	func_proto = btf_type_by_id(btf, func->type);
-	args = btf_params(func_proto);
-	stack_args = sub->arg_slot_cnt == btf_type_vlen(func_proto) ? args : NULL;
-	ret = check_outgoing_stack_args(env, caller, sub->arg_slot_cnt,
-					bpf_subprog_name(env, subprog), btf, stack_args);
-	if (ret)
-		return ret;
 
 	fn = &env->bpf_subprog_scratch;
 	gen_subprog_arg_proto(sub, btf, func_proto, fn);
 	meta->fn = fn;
 	meta->func_proto = func_proto;
 
-	/* check that BTF function arguments match actual types that the
-	 * verifier sees.
-	 */
-	for (arg = 0, slot = 0; arg < btf_type_vlen(func_proto); arg++, slot += nslots) {
-		enum bpf_arg_type arg_type = fn->arg_type[arg];
-		argno_t argno = argno_from_arg(slot + 1);
-		const struct btf_type *t;
-		u32 k;
-
-		t = btf_type_skip_modifiers(btf, args[arg].type, NULL);
-		nslots = btf_arg_slots(t);
-
-		if (arg_type == ARG_SCALAR || arg_type == ARG_IGNORE ||
-		    arg_type == ARG_PTR_TO_CTX || arg_type == ARG_PTR_TO_DYNPTR ||
-		    base_type(arg_type) == ARG_PTR_TO_ARENA ||
-		    base_type(arg_type) == ARG_PTR_TO_BTF_ID ||
-		    base_type(arg_type) == ARG_PTR_TO_MEM) {
-			ret = check_func_arg(env, arg, slot, 0, meta, env->insn_idx);
-			if (ret)
-				return ret;
-		} else {
-			verifier_bug(env, "unrecognized %s type %d",
-				     reg_arg_name(env, argno), arg_type);
-			return -EFAULT;
-		}
-
-		for (k = 1; k < nslots; k++) {
-			ret = check_arg_extra_slot(env, caller, slot + k, meta);
-			if (ret)
-				return ret;
-		}
-	}
-
-	return 0;
+	return check_func_args(env, meta, env->insn_idx);
 }
 
-/* Compare BTF of a function call with given bpf_reg_state.
+/*
+ * Check that call-site argument states match a subprog's BTF signature.
+ *
  * Returns:
  * EFAULT - there is a verifier bug. Abort verification.
- * EINVAL - there is a type mismatch or BTF is not available.
+ * Other errors - there is a type mismatch or BTF is not available.
  * 0 - BTF matches with what bpf_reg_state expects.
- * Only PTR_TO_CTX and SCALAR_VALUE states are recognized.
  */
 static int btf_check_subprog_call(struct bpf_verifier_env *env, int subprog,
-				  struct bpf_reg_state *regs,
 				  struct bpf_call_arg_meta *meta)
 {
 	struct bpf_prog *prog = env->prog;
@@ -10951,7 +10909,7 @@ static int btf_check_subprog_call(struct bpf_verifier_env *env, int subprog,
 	if (prog->aux->func_info_aux[subprog].unreliable)
 		return -EINVAL;
 
-	err = btf_check_func_arg_match(env, subprog, btf, regs, meta);
+	err = btf_check_func_arg_match(env, subprog, btf, meta);
 	/* Compiler optimizations can remove arguments from static functions
 	 * or mismatched type can be passed into a global function.
 	 * In such cases mark the function as unreliable from BTF point of view.
@@ -10971,7 +10929,7 @@ static int push_callback_call(struct bpf_verifier_env *env, struct bpf_insn *ins
 	int err;
 
 	caller = state->frame[state->curframe];
-	err = btf_check_subprog_call(env, subprog, caller->regs, &meta);
+	err = btf_check_subprog_call(env, subprog, &meta);
 	if (err == -EFAULT)
 		return err;
 
@@ -11109,7 +11067,7 @@ static int check_func_call(struct bpf_verifier_env *env, struct bpf_insn *insn,
 		return -EFAULT;
 
 	caller = state->frame[state->curframe];
-	err = btf_check_subprog_call(env, subprog, caller->regs, &meta);
+	err = btf_check_subprog_call(env, subprog, &meta);
 	if (err == -EFAULT)
 		return err;
 	if (bpf_subprog_is_global(env, subprog)) {
@@ -11246,7 +11204,7 @@ static int check_func_callx(struct bpf_verifier_env *env, struct bpf_insn *insn,
 
 	/* PTR_TO_FUNC is a pointer to a static subprog */
 	subprog = reg->subprogno;
-	err = btf_check_subprog_call(env, subprog, caller->regs, &meta);
+	err = btf_check_subprog_call(env, subprog, &meta);
 	if (err == -EFAULT)
 		return err;
 
-- 
2.52.0


      parent reply	other threads:[~2026-09-25 21:13 UTC|newest]

Thread overview: 19+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-25 21:12 [PATCH bpf-next v1 00/12] Unify subprog argument checks Amery Hung
2026-09-25 21:12 ` [PATCH bpf-next v1 01/12] bpf: Fix kfunc nullability diagnostics after wide arguments Amery Hung
2026-09-26  8:48   ` Alexei Starovoitov
2026-09-28 17:42     ` Amery Hung
2026-09-25 21:12 ` [PATCH bpf-next v1 02/12] bpf: Identify subprog calls in argument metadata Amery Hung
2026-09-25 21:12 ` [PATCH bpf-next v1 03/12] bpf: Build argument prototypes for subprog calls Amery Hung
2026-09-25 21:12 ` [PATCH bpf-next v1 04/12] bpf: Check subprog scalar arguments in the common path Amery Hung
2026-09-25 22:01   ` bot+bpf-ci
2026-09-25 21:12 ` [PATCH bpf-next v1 05/12] bpf: Check global subprog untrusted " Amery Hung
2026-09-25 21:12 ` [PATCH bpf-next v1 06/12] bpf: Check subprog context " Amery Hung
2026-09-25 21:12 ` [PATCH bpf-next v1 07/12] bpf: Check subprog arena " Amery Hung
2026-09-25 21:12 ` [PATCH bpf-next v1 08/12] bpf: Check subprog dynptr " Amery Hung
2026-09-25 21:26   ` sashiko-bot
2026-09-25 21:12 ` [PATCH bpf-next v1 09/12] bpf: Check global subprog BTF-ID " Amery Hung
2026-09-25 21:12 ` [PATCH bpf-next v1 10/12] bpf: Track packet changes in call metadata Amery Hung
2026-09-26  8:49   ` Alexei Starovoitov
2026-09-28 17:42     ` Amery Hung
2026-09-25 21:12 ` [PATCH bpf-next v1 11/12] bpf: Check global subprog memory arguments in the common path Amery Hung
2026-09-25 21:12 ` Amery Hung [this message]

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=20260925211256.1834061-13-ameryhung@gmail.com \
    --to=ameryhung@gmail.com \
    --cc=alexei.starovoitov@gmail.com \
    --cc=andrii@kernel.org \
    --cc=bpf@vger.kernel.org \
    --cc=daniel@iogearbox.net \
    --cc=eddyz87@gmail.com \
    --cc=kernel-team@meta.com \
    --cc=memxor@gmail.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