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 02/12] bpf: Identify subprog calls in argument metadata
Date: Fri, 25 Sep 2026 14:12:46 -0700 [thread overview]
Message-ID: <20260925211256.1834061-3-ameryhung@gmail.com> (raw)
In-Reply-To: <20260925211256.1834061-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 2792dcf91061..43cae33d9921 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-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 ` Amery Hung [this message]
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 ` [PATCH bpf-next v1 12/12] 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=20260925211256.1834061-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 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.