BPF List
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Yonghong Song" <yonghong.song@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, 09 Oct 2026 07:08:23 +0000	[thread overview]
Message-ID: <sashiko-outbox-164976@kernel.org> (raw)
In-Reply-To: <20261009064221.1240081-1-yonghong.song@linux.dev>

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?

[ ... ]
> @@ -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?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261009064206.1238047-1-yonghong.song@linux.dev?part=3

  reply	other threads:[~2026-10-09  7:08 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 [this message]
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=sashiko-outbox-164976@kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=bpf@vger.kernel.org \
    --cc=sashiko-reviews@lists.linux.dev \
    --cc=yonghong.song@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