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 2/5] bpf: Keep the BPF calling convention for a trampoline on a BPF function
Date: Fri, 9 Oct 2026 19:20:10 +0200 [thread overview]
Message-ID: <cb00a111-06de-4380-861b-ee8ef24bbba9@linux.dev> (raw)
In-Reply-To: <63a98d2d85f35e452858e2313b1c36b9d71dc124b0a9aa0f55ac67f382551818@mail.kernel.org>
On 10/9/26 9:26 AM, bot+bpf-ci@kernel.org wrote:
>> bpf: Keep the BPF calling convention for a trampoline on a BPF function
> TL;DR: On arm64, the identity slot mapping for BPF targets may split a 16-byte
> argument across x7 and the stack; fexit/fentry could then read x8 or
> uninitialised stack, corrupting the traced function's values.
>
>> diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c
>> --- a/kernel/bpf/core.c
>> +++ b/kernel/bpf/core.c
> [ ... ]
>
>> @@ -3342,6 +3342,18 @@ u32 bpf_jit_place_args(const struct bpf_jit_arg_abi *abi,
>> u32 i, k, nslots, slot = 0, nregs_used = 0, stack_off = 0;
>> bool on_stack = false;
>>
>> + /*
>> + * A BPF function is called by BPF code, which passes slot N where
>> + * the kernel convention passes its Nth eightbyte, whatever the
>> + * arguments: no hole, no split refused and no register backfilled.
>> + */
>> + if (fm->bpf_tgt_prog) {
>> + for (i = 0; i < fm->nr_args; i++)
>> + for (k = btf_func_model_arg_slots(fm, i); k > 0; k--, slot++)
>> + pos_of_slot[slot] = slot;
>> + return slot;
>> + }
>> +
> Can this identity mapping split one 16-byte argument across the last
> register and the stack on arm64, which is the only trampoline calling
> bpf_jit_place_args() at this commit?
>
> Before this patch, arm64_arg_abi has no split_at_boundary, so every slot of
> an argument landed either in x0-x7 or on the stack. calc_arg_aux() relies
> on that and only checks the first slot of each argument:
>
> for (i = 0, slot = 0; i < m->nr_args; i++) {
> slots = (m->arg_size[i] + 7) / 8;
> if (a64_arg_on_stack(a->pos_of_slot[slot])) /* passed through register ? */
> break;
> slot += slots;
> }
>
> save_args() then uses each pos_of_slot value of such an "in register"
> argument as a register number:
>
> reg = a->pos_of_slot[slot++];
> if (for_call_origin) {
> emit(A64_LDR64I(reg, A64_SP, bargs_off), ctx);
> ...
> } else {
> emit(A64_STR64I(reg, A64_SP, bargs_off), ctx);
> }
>
> With the identity mapping, a 16-byte argument at BPF slot 7 gets
> pos_of_slot = {7, 8}. This looks reachable: a static subprog can have up
> to 12 argument slots (btf_check_arg_slots(), and
> bpf_jit_supports_stack_args() is true on arm64), and btf_prepare_func_args()
> accepts scalar-only structs up to 16 bytes. The selftest added later in
> this series (e5dd7e2f7244) has such a function:
>
> static __noinline __u64 callee_stack(__u64 a, __u64 b, __u64 c, __u64 d,
> __u64 e, __u64 f, __u64 g,
> struct int128_arg h, __u64 i)
>
> The arm64 JIT passes h.lo in x7 (stack_arg_reg[2]) and h.hi at [SP+0]
> (emit_stack_arg_store(), idx 3). calc_arg_aux() then returns
> args_in_regs = 8, regs_for_args = 9, bstack_for_args = 8 and
> ostack_for_args = 16, so:
>
> - fentry: save_args() stores A64_R(8) into ctx[8]. On arm64, x8 is
> BPF_REG_0 of the calling BPF code (bpf2a64[BPF_REG_0] = A64_R(8)), not
> h.hi, which is still at FP + 32 + 0.
>
> - fexit (BPF_TRAMP_F_CALL_ORIG): save_args(..., true, ...) loads the saved
> value into x8 and never writes oargs_off + 0. The original function then
> reads h.hi from uninitialised trampoline stack. If the split argument is
> the last one, bstack_for_args and ostack_for_args are both 0, and the
> function reads [SP+0] of the trampoline frame, which is the
> bpf_tramp_run_ctx.
>
> Attaching fexit would then change the values the traced BPF function
> computes with, and what it returns.
>
> The new comment says the BPF convention has "no split refused", and the x86
> follow-up f5df67b558e5 ("bpf, x86: Place trampoline arguments by the x86-64
> calling convention") handles a split per slot for x86. But no commit in the
> range updates arch/arm64/net/bpf_jit_comp.c. The int128_tgt_prog selftest
> in e5dd7e2f7244 also runs on __aarch64__, where it would expect ctx[8] == 9
> but read x8.
>
> Should calc_arg_aux(), save_args() and restore_args() on arm64 classify and
> read each slot by its own position (register vs. FP + 32 +
> a64_arg_stack_off()), the way the x86 follow-up does, so that a split
> 16-byte argument works?
Indeed, I missed arm64 case. Will fix it in the next revision.
>
>
> ---
> 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/37897160282
next prev parent reply other threads:[~2026-10-09 17:20 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-09 6:42 [PATCH bpf-next 0/5] bpf: Follow up by-value struct and __int128 argument support Yonghong Song
2026-10-09 6:42 ` [PATCH bpf-next 1/5] selftests/bpf: Test by-value __int128 kfunc arguments at an odd slot Yonghong Song
2026-10-09 7:48 ` bot+bpf-ci
2026-10-09 17:04 ` Yonghong Song
2026-10-09 6:42 ` [PATCH bpf-next 2/5] bpf: Keep the BPF calling convention for a trampoline on a BPF function Yonghong Song
2026-10-09 7:26 ` bot+bpf-ci
2026-10-09 17:20 ` Yonghong Song [this message]
2026-10-10 15:00 ` Alexei Starovoitov
2026-10-12 6:03 ` Yonghong Song
2026-10-09 6:42 ` [PATCH bpf-next 3/5] bpf, x86: Place trampoline arguments by the x86-64 calling convention Yonghong Song
2026-10-09 7:08 ` sashiko-bot
2026-10-09 17:38 ` Yonghong Song
2026-10-09 6:42 ` [PATCH bpf-next 4/5] selftests/bpf: Test trampoline args around a 16-byte aligned stack arg Yonghong Song
2026-10-09 6:51 ` sashiko-bot
2026-10-09 18:12 ` Yonghong Song
2026-10-09 6:42 ` [PATCH bpf-next 5/5] selftests/bpf: Test trampoline args of a BPF function at an odd slot Yonghong Song
2026-10-09 7:48 ` bot+bpf-ci
2026-10-09 18:17 ` 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=cb00a111-06de-4380-861b-ee8ef24bbba9@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