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 v2 02/11] bpf: Identify subprog calls in argument metadata
Date: Mon, 28 Sep 2026 11:14:04 -0700 [thread overview]
Message-ID: <20260928181414.644158-3-ameryhung@gmail.com> (raw)
In-Reply-To: <20260928181414.644158-1-ameryhung@gmail.com>
Prepare subprog calls to use the common check_func_args() path. That
checker distinguishes call kinds through bpf_call_arg_meta, but
btf_check_func_arg_match() leaves both BTF and the function ID zero even
though it validates a program-BTF signature.
Represent a subprog call with a non-NULL BTF and a zero function ID.
Define helpers as NULL BTF plus nonzero ID, and kfuncs as non-NULL BTF
plus nonzero ID. Requiring a nonzero kfunc ID also prevents unavailable
special-kfunc IDs from matching subprog metadata. The corresponding
subprog predicate is introduced later alongside its first use.
Setting BTF would expose checks that treat every BTF-backed call as a
kfunc. Restrict kfunc-only BTF parameter lookup, register admission,
release diagnostics, no-cast alias, and projection handling to actual
kfuncs.
The BTF is not modified here, but bpf_call_arg_meta::btf and several
downstream consumers use non-const pointers. Match those existing types
instead of broadening this series with a const-correctness cleanup.
No functional change is intended.
Signed-off-by: Amery Hung <ameryhung@gmail.com>
---
kernel/bpf/verifier.c | 36 +++++++++++++++++++++++-------------
1 file changed, 23 insertions(+), 13 deletions(-)
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index a57acef6a9e9..c61141617d47 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -8638,18 +8638,27 @@ static bool arg_type_is_scalar(enum bpf_arg_type type)
}
/*
- * A kfunc is named by a BTF ID, which can take the same numeric value as an
- * enum bpf_func_id. Only test meta->func_id against a BPF_FUNC_* once the call
- * is known to be to a helper; meta->btf is set only for a kfunc.
+ * A helper has no BTF and a nonzero function ID. A kfunc has both, while a
+ * BPF subprogram has BTF and a zero function ID.
*/
+static bool is_helper(const struct bpf_call_arg_meta *meta)
+{
+ return !meta->btf && meta->func_id;
+}
+
static bool is_helper_call(const struct bpf_call_arg_meta *meta, enum bpf_func_id func_id)
{
- return !meta->btf && meta->func_id == func_id;
+ return is_helper(meta) && meta->func_id == func_id;
+}
+
+static bool is_kfunc(const struct bpf_call_arg_meta *meta)
+{
+ return meta->btf && meta->func_id;
}
static bool is_kfunc_call(const struct bpf_call_arg_meta *meta, u32 btf_id)
{
- return meta->btf && meta->func_id == btf_id;
+ return is_kfunc(meta) && meta->func_id == btf_id;
}
static int resolve_map_arg_type(struct bpf_verifier_env *env,
@@ -8962,7 +8971,7 @@ static int check_func_arg_release(struct bpf_verifier_env *env, struct bpf_reg_s
verbose(env, "release function %s expects referenced PTR_TO_BTF_ID passed to %s\n",
meta->func_name, reg_arg_name(env, argno));
- if (meta->btf) {
+ if (is_kfunc(meta)) {
const struct btf_param *btf_arg;
const struct btf_type *t;
u32 ref_id;
@@ -9016,7 +9025,7 @@ static int check_reg_type(struct bpf_verifier_env *env, struct bpf_reg_state *re
verifier_bug(env, "unsupported arg type %d", arg_type);
return -EFAULT;
}
- if (meta->btf && base_type(arg_type) == ARG_PTR_TO_BTF_ID &&
+ if (is_kfunc(meta) && base_type(arg_type) == ARG_PTR_TO_BTF_ID &&
(base_type(type) == PTR_TO_BTF_ID || reg2btf_ids[base_type(type)]))
goto found;
@@ -9039,7 +9048,7 @@ static int check_reg_type(struct bpf_verifier_env *env, struct bpf_reg_state *re
if (base_type(arg_type) == ARG_PTR_TO_MEM)
type &= ~DYNPTR_TYPE_FLAG_MASK;
/* Allow allocated memory for kfunc ARG_PTR_TO_MEM but not helper. */
- if (meta->btf && base_type(arg_type) == ARG_PTR_TO_MEM &&
+ if (is_kfunc(meta) && base_type(arg_type) == ARG_PTR_TO_MEM &&
type_is_ptr_alloc_obj(type))
type = PTR_TO_MEM;
@@ -9362,7 +9371,8 @@ static int check_func_arg(struct bpf_verifier_env *env, u32 arg, u32 slot, u32 p
struct bpf_call_arg_meta *meta,
int insn_idx)
{
- const struct btf_param *btf_arg = meta->btf ? &btf_params(meta->func_proto)[arg] : NULL;
+ const struct btf_param *btf_arg = is_kfunc(meta) ?
+ &btf_params(meta->func_proto)[arg] : NULL;
const struct bpf_func_proto *fn = meta->fn;
struct bpf_func_state *caller = cur_func(env);
struct bpf_reg_state *regs = cur_regs(env);
@@ -10788,7 +10798,7 @@ static int setup_func_entry(struct bpf_verifier_env *env, int subprog, int calls
}
static int btf_check_func_arg_match(struct bpf_verifier_env *env, int subprog,
- const struct btf *btf,
+ struct btf *btf,
struct bpf_reg_state *regs)
{
struct bpf_subprog_info *sub = subprog_info(env, subprog);
@@ -10800,8 +10810,8 @@ static int btf_check_func_arg_match(struct bpf_verifier_env *env, int subprog,
u32 i;
int ret, err;
- /* Leave btf and func_id zero: this is neither a helper nor a kfunc. */
memset(&meta, 0, sizeof(meta));
+ meta.btf = btf;
meta.func_name = bpf_subprog_name(env, subprog);
ret = btf_prepare_func_args(env, subprog);
@@ -13781,7 +13791,7 @@ static int process_arg_ptr_to_btf_id(struct bpf_verifier_env *env, struct bpf_re
* resolve types.
*/
if ((arg_type_is_release(arg_type) && !is_helper_call(meta, BPF_FUNC_sk_release)) ||
- (meta->btf && btf_type_ids_nocast_alias(&env->log, reg_btf, reg_btf_id,
+ (is_kfunc(meta) && btf_type_ids_nocast_alias(&env->log, reg_btf, reg_btf_id,
arg_btf, arg_btf_id)))
strict_type_match = true;
@@ -13798,7 +13808,7 @@ static int process_arg_ptr_to_btf_id(struct bpf_verifier_env *env, struct bpf_re
* actually use it -- it must cast to the underlying type. So we allow
* caller to pass in the underlying type.
*/
- taking_projection = meta->btf && btf_is_projection_of(arg_tname, reg_tname);
+ taking_projection = is_kfunc(meta) && btf_is_projection_of(arg_tname, reg_tname);
if (!taking_projection && !struct_same) {
verbose(env, "%s %s expected pointer to %s %s but %s has a pointer to %s %s\n",
meta->func_name, reg_arg_name(env, argno),
--
2.52.0
next prev parent reply other threads:[~2026-09-28 18:14 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-28 18:14 [PATCH bpf-next v2 00/11] Unify subprog argument checks Amery Hung
2026-09-28 18:14 ` [PATCH bpf-next v2 01/11] bpf: Fix kfunc BTF parameter lookups after wide arguments Amery Hung
2026-09-28 18:14 ` Amery Hung [this message]
2026-09-28 18:14 ` [PATCH bpf-next v2 03/11] bpf: Build argument prototypes for subprog calls Amery Hung
2026-09-28 18:14 ` [PATCH bpf-next v2 04/11] bpf: Check subprog scalar arguments in the common path Amery Hung
2026-09-28 18:14 ` [PATCH bpf-next v2 05/11] bpf: Check global subprog untrusted " Amery Hung
2026-09-28 18:14 ` [PATCH bpf-next v2 06/11] bpf: Check subprog context " Amery Hung
2026-09-28 18:14 ` [PATCH bpf-next v2 07/11] bpf: Check subprog arena " Amery Hung
2026-09-28 18:14 ` [PATCH bpf-next v2 08/11] bpf: Check subprog dynptr " Amery Hung
2026-09-28 18:28 ` sashiko-bot
2026-09-28 18:33 ` Amery Hung
2026-09-28 18:14 ` [PATCH bpf-next v2 09/11] bpf: Check global subprog BTF-ID " Amery Hung
2026-09-28 18:14 ` [PATCH bpf-next v2 10/11] bpf: Check global subprog memory " Amery Hung
2026-09-28 18:14 ` [PATCH bpf-next v2 11/11] bpf: Check all subprog " Amery Hung
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=20260928181414.644158-3-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