From: Yonghong Song <yonghong.song@linux.dev>
To: sashiko-reviews@lists.linux.dev
Cc: bpf@vger.kernel.org
Subject: Re: [PATCH bpf-next 3/5] bpf, x86: Place trampoline arguments by the x86-64 calling convention
Date: Fri, 9 Oct 2026 19:38:39 +0200 [thread overview]
Message-ID: <ea470d9c-de17-4b1c-9cbe-174e30c44f88@linux.dev> (raw)
In-Reply-To: <sashiko-outbox-164976@kernel.org>
On 10/9/26 9:08 AM, sashiko-bot@kernel.org wrote:
> Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
> - [High] bpf, x86: stack arguments offset mismatch and misalignment with BPF_TRAMP_F_TAIL_CALL_CTX
> - [Medium] bpf: info leak of uninitialized kernel stack memory due to missing garbage cleanup
> --
>
> commit ffb54c9ff7ace6fffcfc471ab2c2927e34131e44
> Author: Yonghong Song <yonghong.song@linux.dev>
>
> bpf, x86: Place trampoline arguments by the x86-64 calling convention
>
> This commit updates the BPF trampoline to place on-stack arguments
> according to the x86-64 calling convention. It introduces a backfill
> mechanism using bpf_jit_place_args() to handle arguments like __int128
> that may span stack slots and create alignment holes.
>
>> diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c
>> index 083fcd6cf15b7..0fc7715e569b5 100644
>> --- a/arch/x86/net/bpf_jit_comp.c
>> +++ b/arch/x86/net/bpf_jit_comp.c
> [ ... ]
>> @@ -3472,8 +3479,35 @@ static void save_args(const struct btf_func_model *m, u8 **prog,
>> *
>> * the arg1-5,arg7 will be passed by regs, and arg6 will
>> * by stack.
>> + *
>> + * An argument aligned to 16 bytes, an __int128 or a struct
>> + * holding one, also starts at an even stack slot, which can
>> + * leave a hole before it. bpf_jit_place_args() worked out
>> + * where each eightbyte is.
>> */
>> - if (nr_regs + arg_regs > 6) {
>> + for (j = 0; j < arg_regs; j++, slot++, bargs_off -= 8) {
>> + u8 pos = pos_of_slot[slot];
>> + u32 src;
>> +
>> + if (!x86_arg_on_stack(pos)) {
> [ ... ]
>> + /* copy function arguments from origin stack frame
>> + * into current stack frame.
> [ ... ]
>> + *
>> + * The area for the origin call mirrors the incoming
>> + * one, hole and all; only the bpf program takes the
>> + * arguments packed.
>> */
>> - for (j = 0; j < arg_regs; j++) {
>> - emit_ldx(prog, BPF_DW, BPF_REG_0, BPF_REG_FP,
>> - nr_stack_slots * 8 + stack_args_off);
>> - if (arena_arg)
>> - emit_arena_arg_conv(prog, BPF_REG_0, nullable,
>> - (u32)arena_base);
>> - emit_stx(prog, BPF_DW, BPF_REG_FP, BPF_REG_0,
>> - -stack_size);
>> -
>> - if (!nr_stack_slots)
>> - first_off = stack_size;
>> - stack_size -= 8;
>> - nr_stack_slots++;
>> - }
>> + off = x86_arg_stack_off(pos);
>> + doff = for_call_origin ? stack_size - off : bargs_off;
>> + emit_ldx(prog, BPF_DW, BPF_REG_0, BPF_REG_FP,
>> + stack_args_off + off);
>> + if (arena_arg)
>> + emit_arena_arg_conv(prog, BPF_REG_0, nullable,
>> + (u32)arena_base);
>> + emit_stx(prog, BPF_DW, BPF_REG_FP, BPF_REG_0, -doff);
>> +
>> + if (!nr_stack_slots)
>> + first_off = doff;
>> + nr_stack_slots++;
>> }
>> }
>>
>> clean_stack_garbage(m, prog, nr_stack_slots, first_off);
>> }
> [Severity: Medium]
> Does this code leak uninitialized kernel stack memory?
>
> The x86-64 ABI allocates 8-byte stack slots for arguments, but compilers
> frequently use 32-bit instructions to place 32-bit arguments, leaving the upper
> 4 bytes of the slot uninitialized.
>
> Since clean_stack_garbage() explicitly returns early when nr_stack_slots != 1,
> copying the full 64 bits with emit_ldx(..., BPF_DW, ...) captures this
> uninitialized kernel memory into the BPF context. Can this leak kernel stack
> memory to privileged BPF users if there are multiple stack arguments?
We probably will be okay since for bpf program, the return value will be
narrowed based on return type.
>
> [ ... ]
>> @@ -4011,8 +4014,8 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *rw_im
>> }
>>
>> if (flags & BPF_TRAMP_F_CALL_ORIG) {
>> - restore_regs(m, &prog, regs_off);
>> - save_args(m, &prog, arg_stack_off, true, flags, 0);
>> + restore_regs(&prog, pos_of_slot, nr_regs, regs_off);
>> + save_args(m, &prog, pos_of_slot, arg_stack_off, true, flags, 0);
>>
>> if (flags & BPF_TRAMP_F_TAIL_CALL_CTX) {
>> /* Before calling the original function, load the
> [Severity: High]
> Are stack arguments misaligned here if BPF_TRAMP_F_TAIL_CALL_CTX is active?
>
> When __arch_prepare_bpf_trampoline() executes, it checks for
> BPF_TRAMP_F_TAIL_CALL_CTX and emits a push rax instruction (pushing 8 bytes)
> after sub rsp, stack_size, which permanently shifts RSP down by 8 bytes.
>
> However, the updated save_args() calculates the stack argument offsets based on
> the original stack_size (doff = stack_size - off) without accounting for this
> extra 8-byte shift.
>
> Because the push rax is unpopped before call orig_call, the original function
> will read its first stack argument from [RSP + 8]. Due to the 8-byte shift,
> this points to the tail call counter pointer instead of the actual first stack
> argument, corrupting all on-stack arguments.
>
> Additionally, doesn't this 8-byte shift break the required 16-byte stack
> alignment on function entry for x86-64?
This patch just allows 16-byte aligned parameters with possible holes. The
rest of change should be the same as the original code. Here you mentioned
a 'push rax' before calling orig_call. These should be okay, 16-byte aligned
parameters may have holes but it should not damage the 'push rax' or calling
orig_call. I will see whether we can add some tests for this.
next prev parent reply other threads:[~2026-10-09 17:38 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
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 [this message]
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=ea470d9c-de17-4b1c-9cbe-174e30c44f88@linux.dev \
--to=yonghong.song@linux.dev \
--cc=bpf@vger.kernel.org \
--cc=sashiko-reviews@lists.linux.dev \
/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