BPF List
 help / color / mirror / Atom feed
From: Yonghong Song <yonghong.song@linux.dev>
To: bot+bpf-ci@kernel.org, bpf@vger.kernel.org
Cc: ast@kernel.org, andrii@kernel.org, daniel@iogearbox.net,
	jose.marchesi@oracle.com, kernel-team@fb.com,
	martin.lau@kernel.org, eddyz87@gmail.com, clm@meta.com,
	ihor.solodrai@linux.dev
Subject: Re: [PATCH bpf-next v2 04/23] bpf: Set sub->arg_cnt earlier in btf_prepare_func_args()
Date: Sat, 9 May 2026 14:05:44 +0100	[thread overview]
Message-ID: <ab015da5-86ef-40f9-b696-c17154c8375b@linux.dev> (raw)
In-Reply-To: <25d29e25e7715da21371ee7d4a7b5445cd8c8eca4dad9ff2d3e34d39fb68c906@mail.kernel.org>



On 5/7/26 12:11 AM, bot+bpf-ci@kernel.org wrote:
>> diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c
>> index 77af44d8a3ad..a33a5b4122f8 100644
>> --- a/kernel/bpf/btf.c
>> +++ b/kernel/bpf/btf.c
>> @@ -7880,6 +7880,7 @@ int btf_prepare_func_args(struct bpf_verifier_env *env, int subprog)
>>   	}
>>   	args = (const struct btf_param *)(t + 1);
>>   	nargs = btf_type_vlen(t);
>> +	sub->arg_cnt = nargs;
>>   	if (nargs > MAX_BPF_FUNC_REG_ARGS) {
>>   		if (!is_global)
>>   			return -EINVAL;
>> @@ -8067,7 +8068,6 @@ int btf_prepare_func_args(struct bpf_verifier_env *env, int subprog)
>>   		return -EINVAL;
>>   	}
>>
>> -	sub->arg_cnt = nargs;
>>   	sub->args_cached = true;
>>
>>   	return 0;
>
> ---
> AI reviewed your patch. Please fix the bug or email reply why it's not a bug.

sub->arg_cnt is used in two places:

First, function btf_check_func_arg_match():

static int btf_check_func_arg_match(struct bpf_verifier_env *env, int subprog,
                                     const struct btf *btf,
                                     struct bpf_reg_state *regs)
{
         struct bpf_subprog_info *sub = subprog_info(env, subprog);
         struct bpf_func_state *caller = cur_func(env);
         struct bpf_verifier_log *log = &env->log;
         u32 i;
         int ret;

         ret = btf_prepare_func_args(env, subprog);
         if (ret)
                 return ret;

         ret = check_outgoing_stack_args(env, caller, sub->arg_cnt);
         if (ret)
                 return ret;

         /* check that BTF function arguments match actual types that the
          * verifier sees.
          */
         for (i = 0; i < sub->arg_cnt; i++) {
		...
	}
	...
}

In this case, btf_prepare_func_args return failure and sub->arg_cnt will
not be used any more. So for this case, the patch won't make a difference.

Second, function do_check_common():

         if (subprog || env->prog->type == BPF_PROG_TYPE_EXT) {
                 const char *sub_name = subprog_name(env, subprog);
                 struct bpf_subprog_arg_info *arg;
                 struct bpf_reg_state *reg;

                 if (env->log.level & BPF_LOG_LEVEL)
                         verbose(env, "Validating %s() func#%d...\n", sub_name, subprog);
                 ret = btf_prepare_func_args(env, subprog);
                 if (ret)
                         goto out;

                 if (subprog_is_exc_cb(env, subprog)) {
                         state->frame[0]->in_exception_callback_fn = true;
                 
                         /*
                          * Global functions are scalar or void, make sure
                          * we return a scalar.
                          * we return a scalar.
                          */
                         if (subprog_returns_void(env, subprog)) {
                                 verbose(env, "exception cb cannot return void\n");
                                 ret = -EINVAL;
                                 goto out;
                         }

                         /* Also ensure the callback only has a single scalar argument. */
                         if (sub->arg_cnt != 1 || sub->args[0].arg_type != ARG_ANYTHING) {
                                 verbose(env, "exception cb only supports single integer argument\n");
                                 ret = -EINVAL;
                                 goto out;
                         }
                 }
                 for (i = BPF_REG_1; i <= min_t(u32, sub->arg_cnt, MAX_BPF_FUNC_REG_ARGS); i++) {
                         arg = &sub->args[i - BPF_REG_1];
                         reg = &regs[i];

                         if (arg->arg_type == ARG_PTR_TO_CTX) {
                                 reg->type = PTR_TO_CTX;
                                 mark_reg_known_zero(env, regs, i);
                         } else if (arg->arg_type == ARG_ANYTHING) {
                                 reg->type = SCALAR_VALUE;
                                 mark_reg_unknown(env, regs, i);
                         } else if (arg->arg_type == ARG_PTR_TO_DYNPTR) {
                                 /* assume unspecial LOCAL dynptr type */
                                 __mark_dynptr_reg(reg, BPF_DYNPTR_TYPE_LOCAL, true, ++env->id_gen);
                         } else if (base_type(arg->arg_type) == ARG_PTR_TO_MEM) {
                                 reg->type = PTR_TO_MEM;
                                 reg->type |= arg->arg_type &
                                              (PTR_MAYBE_NULL | PTR_UNTRUSTED | MEM_RDONLY);
                                 mark_reg_known_zero(env, regs, i);
                                 reg->mem_size = arg->mem_size;
                                 if (arg->arg_type & PTR_MAYBE_NULL)
                                         reg->id = ++env->id_gen;
                         } else if (base_type(arg->arg_type) == ARG_PTR_TO_BTF_ID) {
                                 reg->type = PTR_TO_BTF_ID;
                                 if (arg->arg_type & PTR_MAYBE_NULL)
                                         reg->type |= PTR_MAYBE_NULL;
                                 if (arg->arg_type & PTR_UNTRUSTED)
                                         reg->type |= PTR_UNTRUSTED;
                                 if (arg->arg_type & PTR_TRUSTED)
                                         reg->type |= PTR_TRUSTED;
                                 mark_reg_known_zero(env, regs, i);
                                 reg->btf = bpf_get_btf_vmlinux(); /* can't fail at this point */
                                 reg->btf_id = arg->btf_id;
                                 reg->id = ++env->id_gen;
                         } else if (base_type(arg->arg_type) == ARG_PTR_TO_ARENA) {
                                 /* caller can pass either PTR_TO_ARENA or SCALAR */
                                 mark_reg_unknown(env, regs, i);
                         } else {
                                 verifier_bug(env, "unhandled arg#%d type %d",
                                              i - BPF_REG_1 + 1, arg->arg_type);
                                 ret = -EFAULT;
                                 goto out;
                         }
                 }
                 if (env->prog->type == BPF_PROG_TYPE_EXT && sub->arg_cnt > MAX_BPF_FUNC_REG_ARGS) {
                         verbose(env, "freplace programs with >%d args not supported yet\n",
                                 MAX_BPF_FUNC_REG_ARGS);
                         ret = -EINVAL;
                         goto out;
                 }
         } else {
                 /* if main BPF program has associated BTF info, validate that
                  * it's matching expected signature, and otherwise mark BTF
                  * info for main program as unreliable
                  */
                 if (env->prog->aux->func_info_aux) {
                         ret = btf_prepare_func_args(env, 0);
                         if (ret || sub->arg_cnt != 1 || sub->args[0].arg_type != ARG_PTR_TO_CTX)
                                 env->prog->aux->func_info_aux[0].unreliable = true;
                 }

                 /* 1st arg to a function */
                 regs[BPF_REG_1].type = PTR_TO_CTX;
                 mark_reg_known_zero(env, regs, BPF_REG_1);
         }

For the then brach of 'if (subprog || env->prog->type == BPF_PROG_TYPE_EXT)',
if btf_prepare_func_args() fails, the error will return.

But the else branch of 'if (subprog || env->prog->type == BPF_PROG_TYPE_EXT)',
if btf_prepare_func_args() fails, the verification will still continue.
So it makes sense to get sub->arg_cnt earlier in btf_prepare_func_args()
since sub->arg_cnt is needed later on.

> See: https://github.com/kernel-patches/vmtest/blob/master/ci/claude/README.md
>
> CI run summary: https://github.com/kernel-patches/bpf/actions/runs/25523765323


  reply	other threads:[~2026-05-09 13:05 UTC|newest]

Thread overview: 68+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-05-07 21:29 [PATCH bpf-next v2 00/23] bpf: Support stack arguments for BPF functions and kfuncs Yonghong Song
2026-05-07 21:29 ` [PATCH bpf-next v2 01/23] bpf: Convert bpf_get_spilled_reg macro to static inline function Yonghong Song
2026-05-07 21:29 ` [PATCH bpf-next v2 02/23] bpf: Remove copy_register_state wrapper function Yonghong Song
2026-05-07 21:29 ` [PATCH bpf-next v2 03/23] bpf: Add helper functions for r11-based stack argument insns Yonghong Song
2026-05-07 21:30 ` [PATCH bpf-next v2 04/23] bpf: Set sub->arg_cnt earlier in btf_prepare_func_args() Yonghong Song
2026-05-07 22:11   ` bot+bpf-ci
2026-05-09 13:05     ` Yonghong Song [this message]
2026-05-07 21:30 ` [PATCH bpf-next v2 05/23] bpf: Support stack arguments for bpf functions Yonghong Song
2026-05-07 22:26   ` bot+bpf-ci
2026-05-09 12:52     ` Yonghong Song
2026-05-08 18:00   ` Alexei Starovoitov
2026-05-09 12:55     ` Yonghong Song
2026-05-07 21:30 ` [PATCH bpf-next v2 06/23] bpf: Refactor jmp history to use dedicated spi/frame fields Yonghong Song
2026-05-07 21:30 ` [PATCH bpf-next v2 07/23] bpf: Add precision marking and backtracking for stack argument slots Yonghong Song
2026-05-07 22:11   ` bot+bpf-ci
2026-05-09 13:08     ` Yonghong Song
2026-05-09  4:05   ` sashiko-bot
2026-05-10 16:41     ` Yonghong Song
2026-05-07 21:30 ` [PATCH bpf-next v2 08/23] bpf: Refactor record_call_access() to extract per-arg logic Yonghong Song
2026-05-07 21:30 ` [PATCH bpf-next v2 09/23] bpf: Extend liveness analysis to track stack argument slots Yonghong Song
2026-05-07 22:11   ` bot+bpf-ci
2026-05-09 13:29     ` Yonghong Song
2026-05-09  0:59   ` sashiko-bot
2026-05-10 16:47     ` Yonghong Song
2026-05-07 21:30 ` [PATCH bpf-next v2 10/23] bpf: Reject stack arguments in non-JITed programs Yonghong Song
2026-05-07 22:11   ` bot+bpf-ci
2026-05-09  2:10   ` sashiko-bot
2026-05-10 16:59     ` Yonghong Song
2026-05-07 21:30 ` [PATCH bpf-next v2 11/23] bpf: Prepare architecture JIT support for stack arguments Yonghong Song
2026-05-09  2:19   ` sashiko-bot
2026-05-10 17:05     ` Yonghong Song
2026-05-07 21:30 ` [PATCH bpf-next v2 12/23] bpf: Enable r11 based insns Yonghong Song
2026-05-09  2:59   ` sashiko-bot
2026-05-10 17:11     ` Yonghong Song
2026-05-07 21:30 ` [PATCH bpf-next v2 13/23] bpf: Support stack arguments for kfunc calls Yonghong Song
2026-05-07 21:30 ` [PATCH bpf-next v2 14/23] bpf: Reject stack arguments if tail call reachable Yonghong Song
2026-05-07 22:11   ` bot+bpf-ci
2026-05-09  1:42   ` sashiko-bot
2026-05-10 17:15     ` Yonghong Song
2026-05-07 21:30 ` [PATCH bpf-next v2 15/23] bpf,x86: Implement JIT support for stack arguments Yonghong Song
2026-05-07 22:26   ` bot+bpf-ci
2026-05-10 17:21     ` Yonghong Song
2026-05-09  2:21   ` sashiko-bot
2026-05-10 17:22     ` Yonghong Song
2026-05-07 21:31 ` [PATCH bpf-next v2 16/23] selftests/bpf: Add tests for BPF function " Yonghong Song
2026-05-07 21:31 ` [PATCH bpf-next v2 17/23] selftests/bpf: Add tests for stack argument validation Yonghong Song
2026-05-09  1:30   ` sashiko-bot
2026-05-10 17:23     ` Yonghong Song
2026-05-07 21:31 ` [PATCH bpf-next v2 18/23] selftests/bpf: Add BTF fixup for __naked subprog parameter names Yonghong Song
2026-05-09  1:40   ` sashiko-bot
2026-05-10 17:24     ` Yonghong Song
2026-05-07 21:31 ` [PATCH bpf-next v2 19/23] selftests/bpf: Add verifier tests for stack argument validation Yonghong Song
2026-05-07 22:11   ` bot+bpf-ci
2026-05-10 17:27     ` Yonghong Song
2026-05-09  1:38   ` sashiko-bot
2026-05-10 17:27     ` Yonghong Song
2026-05-07 21:31 ` [PATCH bpf-next v2 20/23] selftests/bpf: Add precision backtracking test for stack arguments Yonghong Song
2026-05-09  1:52   ` sashiko-bot
2026-05-10 17:31     ` Yonghong Song
2026-05-07 21:31 ` [PATCH bpf-next v2 21/23] bpf, arm64: Map BPF_REG_0 to x8 instead of x7 Yonghong Song
2026-05-08 18:01   ` Alexei Starovoitov
2026-05-09 13:44     ` Yonghong Song
2026-05-07 21:32 ` [PATCH bpf-next v2 22/23] bpf, arm64: Add JIT support for stack arguments Yonghong Song
2026-05-09  2:15   ` sashiko-bot
2026-05-10 17:32     ` Yonghong Song
2026-05-07 21:32 ` [PATCH bpf-next v2 23/23] selftests/bpf: Enable stack argument tests for arm64 Yonghong Song
2026-05-08 18:06 ` [PATCH bpf-next v2 00/23] bpf: Support stack arguments for BPF functions and kfuncs Alexei Starovoitov
2026-05-09 13:43   ` Yonghong Song

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=ab015da5-86ef-40f9-b696-c17154c8375b@linux.dev \
    --to=yonghong.song@linux.dev \
    --cc=andrii@kernel.org \
    --cc=ast@kernel.org \
    --cc=bot+bpf-ci@kernel.org \
    --cc=bpf@vger.kernel.org \
    --cc=clm@meta.com \
    --cc=daniel@iogearbox.net \
    --cc=eddyz87@gmail.com \
    --cc=ihor.solodrai@linux.dev \
    --cc=jose.marchesi@oracle.com \
    --cc=kernel-team@fb.com \
    --cc=martin.lau@kernel.org \
    /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