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,
	eddyz87@gmail.com, kernel-team@fb.com, martin.lau@kernel.org,
	mason@kernel.org, ihor.solodrai@linux.dev
Subject: Re: [PATCH bpf-next 05/12] bpf: Support by-value struct and __int128 kfunc arguments
Date: Mon, 7 Sep 2026 21:23:34 -0700	[thread overview]
Message-ID: <8e59b431-3124-46a4-b6d6-1e1ae59f08c4@linux.dev> (raw)
In-Reply-To: <b596aa791c607e639b08d2e6bd6a4a3a9ed28e39bade2364e4b77a2e01678cdc@mail.kernel.org>



On 9/3/26 11:24 PM, bot+bpf-ci@kernel.org wrote:
>> diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
>> index 17e576c7b757..030fb37c22ef 100644
>> --- a/kernel/bpf/verifier.c
>> +++ b/kernel/bpf/verifier.c
> [ ... ]
>
>> @@ -12792,29 +12904,34 @@ static int check_kfunc_args(struct bpf_verifier_env *env, struct bpf_call_arg_me
>>   	const struct btf *btf = meta->btf;
>>   	const struct btf_param *args;
>>   	struct btf_record *rec;
>> -	u32 i, nargs;
>> +	u32 i, k, nargs, proto_slots, slots_used, nslots = 0;
>>   	int ret;
>>
>>   	args = (const struct btf_param *)(meta->func_proto + 1);
>>   	nargs = btf_type_vlen(meta->func_proto);
>> +	proto_slots = kfunc_proto_slots(btf, meta->func_proto);
>>
>> -	ret = check_outgoing_stack_args(env, caller, nargs, func_name, btf, args);
>> +	ret = check_outgoing_stack_args(env, caller, proto_slots, func_name, btf,
>> +					proto_slots == nargs ? args : NULL);
>>   	if (ret)
>>   		return ret;
>>
>>   	/* Check that BTF function arguments match actual types that the
>>   	 * verifier sees.
>>   	 */
>> -	for (i = 0; i < nargs; i++) {
>> -		struct bpf_reg_state *reg = get_func_arg_reg(caller, regs, i);
>> +	for (i = 0, slots_used = 0; i < nargs; i++, slots_used += nslots) {
>> +		struct bpf_reg_state *reg = get_func_arg_reg(caller, regs, slots_used);
>>   		const struct btf_type *t, *ref_t, *resolve_ret;
>>   		enum bpf_arg_type arg_type = ARG_DONTCARE;
>> -		argno_t argno = argno_from_arg(i + 1);
>> +		argno_t argno = argno_from_arg(slots_used + 1);
>>   		int regno = reg_from_argno(argno);
>>   		bool btf_id_fixed_off_ok = true;
>>   		u32 ref_id = args[i].type, type_size;
>>   		int kf_arg_type = meta->fn->arg_type[i];
>>
>> +		t = btf_type_skip_modifiers(btf, args[i].type, NULL);
>> +		nslots = kfunc_arg_slots(t);
>> +
> This converts the argument walk to slot-based indexing, where 'reg' and
> 'argno' now come from 'slots_used' rather than 'i'.  Before this patch
> every parameter took exactly one slot, so parameter index and slot
> index were the same number.  After this patch they diverge whenever a
> parameter takes two slots.
>
> The KF_ARG_MEM_SIZE case, ~500 lines further down in check_kfunc_args(),
> was not converted.  It still resolves the buffer register by parameter
> index:
>
> kernel/bpf/verifier.c:check_kfunc_args() {
>      ...
>      case KF_ARG_MEM_SIZE:
>      {
>          struct bpf_reg_state *buff_reg = get_func_arg_reg(caller, regs, i - 1);
>          struct bpf_reg_state *size_reg = reg;
>          argno_t buff_argno = argno_from_arg(i);
>      ...
> }
>
> For a kfunc such as
>
>      void bpf_x(__int128 v, void *p, u32 p__sz);
>
> v occupies slots 0-1 (R1, R2), p slot 2 (R3), p__sz slot 3 (R4).  At
> i == 2, slots_used == 3, so 'reg' and 'argno' correctly select R4, but
> buff_reg = get_func_arg_reg(caller, regs, i - 1) selects R2 (the upper
> eightbyte of v) instead of R3, the pointer the length actually
> describes.  The same applies to a 16-byte by-value struct parameter,
> exactly the shape this patch exists to enable.
>
> The consequence is a validation hole, not just a bad diagnostic.  R2 is
> a SCALAR_VALUE, so when the program passes a __int128 (or struct) whose
> upper eightbyte is zero -- the common case for any value that fits in
> 64 bits -- bpf_register_is_null(buff_reg) is true and the case breaks
> out early:
>
>          if (bpf_register_is_null(buff_reg))
>              break;
>
> check_mem_size_reg() is then never called, so neither p nor p__sz is
> checked.  The pointer's own iteration does not cover it either:
> get_kfunc_arg_type() classifies a pointer followed by a __sz parameter
> as plain KF_ARG_PTR_TO_MEM without MEM_FIXED_SIZE, and that switch arm
> only validates size when MEM_FIXED_SIZE is set.  The program therefore
> loads and the kfunc runs with an unbounded length against p.  When the
> upper eightbyte is non-zero the failure inverts into a spurious
> rejection, since check_mem_size_reg() is handed a scalar as the memory
> pointer.  buff_argno = argno_from_arg(i) is wrong in the same way and
> feeds the wrong register into the diagnostics and into
> mark_stack_arg_precision()/mark_chain_precision() via
> check_mem_size_reg().

Yes, I missed this one. Will fix.

>
> At this commit gen_kfunc_arg_proto() gates every nslots > 1 argument on
> bpf_jit_supports_kfunc_arg_slot(), whose __weak default in
> kernel/bpf/core.c returns false, so multi-slot kfunc arguments are
> still refused.  Within the stated range
> db649eef61418e5d0289d88bcdd663e510756589..9ad88f2069ccb8b9d464230a3d04082baaffe4e0,
> commit 2924cde3ca70 ("bpf, x86: Place kfunc arguments per the SysV
> calling convention") and commit e958bc6f838b ("bpf, arm64: Place kfunc
> arguments per AAPCS64") enable the path, and no commit in that range
> touches kernel/bpf/verifier.c again apart from db9461ba111c adding
> btf_type_align16().
>
> Both uses should be derived from the slot walk, e.g.
> get_func_arg_reg(caller, regs, slots_used - 1) and
> argno_from_arg(slots_used).
>
> ---
>
> commit db649eef61418e5d0289d88bcdd663e510756589
> Author: Yonghong Song <yonghong.song@linux.dev>
>
>>      bpf: Support by-value struct and __int128 kfunc arguments
>>
>>      A kfunc taking a struct or union by value is rejected today, and one
>>      taking an __int128 is accepted but mis-counted:
>>
>>        Unrecognized R2 type STRUCT
>>
>>      Give the kfunc argument walk the same slot count a BPF-to-BPF call now
>>      uses: one argument register per eightbyte, so a 16-byte value takes two.
>>      The outgoing stack argument count at the call site follows the slots for
>>      the same reason. Similar to BPF-to-BPF aggregate handling, a kfunc
>>      aggregate argument only supports tbe composed of scalars.
>>
>>      Signed-off-by: Yonghong Song <yonghong.song@linux.dev>
> This looks like a bug fix for kfunc argument handling introduced in
> commit 1690dcf27c73 ("bpf: Classify scalar kfunc arguments from BTF"),
> which added get_kfunc_arg_type() that only handled scalar and pointer
> types, causing struct/union types to be rejected with 'Unrecognized R2
> type STRUCT' and __int128 arguments to be mis-counted.  Should this
> include:
>
>    Fixes: 1690dcf27c73 ("bpf: Classify scalar kfunc arguments from BTF")
>
>
> ---
> AI reviewed your patch. Please fix the bug or email reply why it's not a bug.
> See: https://github.com/kernel-patches/vmtest/blob/master/ci/claude/README.md
>
> CI run summary: https://github.com/kernel-patches/bpf/actions/runs/33840714551


  reply	other threads:[~2026-09-08  4:23 UTC|newest]

Thread overview: 46+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-04  5:09 [PATCH bpf-next 00/12] bpf: Support by-value struct and __int128 arguments Yonghong Song
2026-09-04  5:10 ` [PATCH bpf-next 01/12] selftests/bpf: Add a test for an __int128 by-value argument Yonghong Song
2026-09-04  5:10 ` [PATCH bpf-next 02/12] bpf: Index global function arguments by argument slot Yonghong Song
2026-09-04  5:10 ` [PATCH bpf-next 03/12] bpf: Support by-value struct arguments up to 16 bytes Yonghong Song
2026-09-04  5:23   ` sashiko-bot
2026-09-08  4:17     ` Yonghong Song
2026-09-04  6:09   ` bot+bpf-ci
2026-09-08  4:19     ` Yonghong Song
2026-09-04  5:10 ` [PATCH bpf-next 04/12] bpf: Support __int128 as a by-value function argument Yonghong Song
2026-09-04  5:32   ` sashiko-bot
2026-09-08  4:20     ` Yonghong Song
2026-09-04  6:09   ` bot+bpf-ci
2026-09-08  4:21     ` Yonghong Song
2026-09-04  5:10 ` [PATCH bpf-next 05/12] bpf: Support by-value struct and __int128 kfunc arguments Yonghong Song
2026-09-04  6:18   ` sashiko-bot
2026-09-08  4:22     ` Yonghong Song
2026-09-04  6:24   ` bot+bpf-ci
2026-09-08  4:23     ` Yonghong Song [this message]
2026-09-04  5:10 ` [PATCH bpf-next 06/12] bpf: Add a JIT helper for the outgoing stack of kfunc calls Yonghong Song
2026-09-04  5:25   ` sashiko-bot
2026-09-08  4:26     ` Yonghong Song
2026-09-04  5:10 ` [PATCH bpf-next 07/12] bpf, x86: Place kfunc arguments per the SysV calling convention Yonghong Song
2026-09-04  5:36   ` sashiko-bot
2026-09-08  4:27     ` Yonghong Song
2026-09-04 23:58   ` Alexei Starovoitov
2026-09-06 20:15     ` Yonghong Song
2026-09-08  4:33       ` Alexei Starovoitov
2026-09-08  5:02         ` Yonghong Song
2026-09-08  5:10           ` Yonghong Song
2026-09-08 15:24           ` Alexei Starovoitov
2026-09-08 18:43             ` Yonghong Song
2026-09-09  1:59               ` Alexei Starovoitov
2026-09-04  5:10 ` [PATCH bpf-next 08/12] bpf: Record a 16-byte argument alignment in the function model Yonghong Song
2026-09-04  6:09   ` bot+bpf-ci
2026-09-08  4:28     ` Yonghong Song
2026-09-04  5:10 ` [PATCH bpf-next 09/12] bpf, arm64: Place kfunc arguments per AAPCS64 Yonghong Song
2026-09-04  6:09   ` bot+bpf-ci
2026-09-04  5:10 ` [PATCH bpf-next 10/12] selftests/bpf: Add C tests for by-value arguments up to 16 bytes Yonghong Song
2026-09-04  5:19   ` sashiko-bot
2026-09-08  4:33     ` Yonghong Song
2026-09-04  6:09   ` bot+bpf-ci
2026-09-08  4:34     ` Yonghong Song
2026-09-04  5:10 ` [PATCH bpf-next 11/12] selftests/bpf: Add inline-asm tests for by-value arguments Yonghong Song
2026-09-04  6:09   ` bot+bpf-ci
2026-09-08  4:35     ` Yonghong Song
2026-09-04  5:11 ` [PATCH bpf-next 12/12] selftests/bpf: Add tests for by-value kfunc arguments 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=8e59b431-3124-46a4-b6d6-1e1ae59f08c4@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=daniel@iogearbox.net \
    --cc=eddyz87@gmail.com \
    --cc=ihor.solodrai@linux.dev \
    --cc=kernel-team@fb.com \
    --cc=martin.lau@kernel.org \
    --cc=mason@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