All of lore.kernel.org
 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 v5 13/16] bpf,x86: Implement JIT support for stack arguments
Date: Fri, 17 Apr 2026 04:44:42 +0000	[thread overview]
Message-ID: <20260417044443.66D37C19425@smtp.kernel.org> (raw)
In-Reply-To: <20260417034823.2632289-1-yonghong.song@linux.dev>

Sashiko AI review found 4 potential issue(s):
- [High] Data corruption of Argument 6 across function calls due to caller-saved register clobbering.
- [High] Missing size handling for Argument 6 allows verifier bounds tracking bypass and out-of-bounds memory writes.
- [High] The offset translation formula for outgoing arguments 7+ reverses the memory layout, corrupting sub-slot accesses.
- [Medium] The JIT misroutes stack accesses because it rigidly assumes LDX only targets incoming arguments and STX/ST only target outgoing arguments.
--

commit 41dcf99330b6b0a3804185f2a284a76be8340ed1
Author: Yonghong Song <yonghong.song@linux.dev>

bpf,x86: Implement JIT support for stack arguments

Add x86_64 JIT support for BPF functions and kfuncs with more than
5 arguments. The extra arguments are passed through a stack area
addressed by register r11 (BPF_REG_PARAMS) in BPF bytecode,
which the JIT translates to native code.

> diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c
> index 32864dbc2c4e8..25b4357de023b 100644
> --- a/arch/x86/net/bpf_jit_comp.c
> +++ b/arch/x86/net/bpf_jit_comp.c

[ ... ]

> @@ -1664,16 +1692,45 @@ static int do_jit(struct bpf_prog *bpf_prog, int *addrs, u8 *image, u8 *rw_image
>  	stack_depth = bpf_prog->aux->stack_depth;
> +	stack_arg_depth = bpf_prog->aux->stack_arg_depth;
> +	incoming_stack_arg_depth = bpf_prog->aux->incoming_stack_arg_depth;
> +	outgoing_stack_arg_depth = stack_arg_depth - incoming_stack_arg_depth;
>  	priv_stack_ptr = bpf_prog->aux->priv_stack_ptr;
>  	if (priv_stack_ptr) {
>  		priv_frame_ptr = priv_stack_ptr + PRIV_STACK_GUARD_SZ + round_up(stack_depth, 8);
>  		stack_depth = 0;
>  	}
>  
> +	/*
> +	 * Follow x86-64 calling convention for both BPF-to-BPF and
> +	 * kfunc calls:
> +	 *   - Arg 6 is passed in R9 register
> +	 *   - Args 7+ are passed on the stack at [rsp]

Can the use of the R9 register cause data corruption across function calls?

The x86-64 C calling convention defines R9 as a caller-saved register.
However, the BPF verifier models argument 6 as stack memory, which implies
its value should be preserved across calls.

If a BPF program reads incoming argument 6 after making a helper or kfunc
call, will it receive a clobbered value instead of the original argument?
Similarly, could a helper call scheduled by LLVM between the setup of
outgoing argument 6 and the target call corrupt the R9 register?

[ ... ]

> +	/*
> +	 * Base offset from rbp for translating BPF outgoing args 7+
> +	 * to native offsets. BPF uses negative offsets from r11
> +	 * (r11-8 for arg6, r11-16 for arg7, ...) while x86 uses
> +	 * positive offsets from rsp ([rsp+0] for arg7, [rsp+8] for
> +	 * arg8, ...). Arg 6 goes to R9 directly.
> +	 *
> +	 * The translation reverses direction:
> +	 *   native_off = outgoing_arg_base - outgoing_rsp - bpf_off - 16
> +	 *
> +	 * Note that tail_call_reachable is guaranteed to be false when
> +	 * stack args exist, so tcc pushes need not be accounted for.
> +	 */

Does this formula correctly handle multi-byte sub-slot accesses?

Since the formula subtracts the BPF offset, the memory layout within the
8-byte slots appears mathematically reversed. While this correctly maps the
8-byte slot bases (e.g., -16 maps to rsp + 0), it seems to point to the
wrong memory for partial writes.

For example, if a program writes to the upper 32 bits of Arg 7 at BPF offset
-12, the formula yields BASE - (-12) - 16 = BASE - 4. Will this map the
access out-of-bounds below the stack pointer instead of to [rsp + 4]?

[ ... ]

> @@ -2129,12 +2222,26 @@ static int do_jit(struct bpf_prog *bpf_prog, int *addrs, u8 *image, u8 *rw_image
>  				EMIT1(0xC7);
>  			goto st;
>  		case BPF_ST | BPF_MEM | BPF_DW:
> +			if (dst_reg == BPF_REG_PARAMS && insn->off == -8) {
> +				/* Arg 6: store immediate in r9 register */
> +				emit_mov_imm64(&prog, X86_REG_R9, imm32 >> 31, (u32)imm32);
> +				break;
> +			}
>  			EMIT2(add_1mod(0x48, dst_reg), 0xC7);
>  
> -st:			if (is_imm8(insn->off))
> -				EMIT2(add_1reg(0x40, dst_reg), insn->off);
> +st:			insn_off = insn->off;
> +			if (dst_reg == BPF_REG_PARAMS) {
> +				/* Args 7+: reverse BPF negative offsets to
> +				 * x86 positive rsp offsets.
> +				 * BPF off=-16 → [rsp+0], off=-24 → [rsp+8], ...
> +				 */
> +				insn_off = outgoing_arg_base - outgoing_rsp - insn_off - 16;
> +				dst_reg = BPF_REG_FP;
> +			}

Are the size constraints missing for Argument 6 here?

The check for Arg 6 (insn->off == -8) is only implemented under the BPF_DW
case. For sizes B, H, and W, execution will fall through to the st: label.
This would incorrectly translate the access as a normal stack operation
using the formula above, writing out-of-bounds below the stack pointer at
[rsp - 8] instead of populating R9.

Additionally, for BPF_LDX, a 1-byte load emits a full 64-bit move to R9.
Since the upper 56 bits of R9 are undefined for 1-byte arguments, could
they contain garbage data? This would bypass the verifier's strict value
bounds tracking, which assumes the loaded value is strictly within [0, 255].

[ ... ]

> @@ -2243,6 +2360,19 @@ st:			if (is_imm8(insn->off))
>  		case BPF_LDX | BPF_PROBE_MEMSX | BPF_H:
>  		case BPF_LDX | BPF_PROBE_MEMSX | BPF_W:
>  			insn_off = insn->off;
> +			if (src_reg == BPF_REG_PARAMS) {
> +				if (insn_off == 8) {
> +					/* Incoming arg 6: read from r9 */
> +					EMIT_mov(dst_reg, X86_REG_R9);
> +					break;
> +				}
> +				src_reg = BPF_REG_FP;
> +				/*
> +				 * Incoming args 7+: native_off == bpf_off
> +				 * (r11+16 → [rbp+16], r11+24 → [rbp+24], ...)
> +				 * No offset adjustment needed.
> +				 */
> +			}

Does this logic misroute stack accesses by assuming LDX always targets
incoming arguments and STX/ST always target outgoing arguments?

If a program writes an outgoing argument ([r11 - 16]) and then reads it back
via LDX, the JIT appears to apply the incoming argument translation mapping
the read to [rbp - 16] (the local stack) instead of [rsp] (the outgoing
area). This would return uninitialized data.

Conversely, if a program modifies an incoming argument ([r11 + 16]) using
STX, the JIT would apply the outgoing translation formula, yielding
BASE - 16 - 16 = BASE - 32, which writes out-of-bounds below the stack
pointer.

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

  reply	other threads:[~2026-04-17  4:44 UTC|newest]

Thread overview: 73+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-04-17  3:46 [PATCH bpf-next v5 00/16] bpf: Support stack arguments for BPF functions and kfuncs Yonghong Song
2026-04-17  3:47 ` [PATCH bpf-next v5 01/16] bpf: Remove unused parameter from check_map_kptr_access() Yonghong Song
2026-04-17  3:47 ` [PATCH bpf-next v5 02/16] bpf: Refactor to avoid redundant calculation of bpf_reg_state Yonghong Song
2026-04-17  3:47 ` [PATCH bpf-next v5 03/16] bpf: Refactor to handle memory and size together Yonghong Song
2026-04-17  4:49   ` sashiko-bot
2026-04-18 16:40     ` Yonghong Song
2026-04-18  0:52   ` bot+bpf-ci
2026-04-18 16:47     ` Yonghong Song
2026-04-17  3:47 ` [PATCH bpf-next v5 04/16] bpf: Prepare verifier logs for upcoming kfunc stack arguments Yonghong Song
2026-04-17  3:47 ` [PATCH bpf-next v5 05/16] bpf: Introduce bpf register BPF_REG_PARAMS Yonghong Song
2026-04-17  3:47 ` [PATCH bpf-next v5 06/16] bpf: Limit the scope of BPF_REG_PARAMS usage Yonghong Song
2026-04-17  4:30   ` bot+bpf-ci
2026-04-18 16:48     ` Yonghong Song
2026-04-17  4:50   ` sashiko-bot
2026-04-18 16:50     ` Yonghong Song
2026-04-18  1:04   ` bot+bpf-ci
2026-04-18 16:54     ` Yonghong Song
2026-04-17  3:47 ` [PATCH bpf-next v5 07/16] bpf: Reuse MAX_BPF_FUNC_ARGS for maximum number of arguments Yonghong Song
2026-04-17  4:30   ` bot+bpf-ci
2026-04-18 17:00     ` Yonghong Song
2026-04-18  0:52   ` bot+bpf-ci
2026-04-18 17:03     ` Yonghong Song
2026-04-17  3:47 ` [PATCH bpf-next v5 08/16] bpf: Support stack arguments for bpf functions Yonghong Song
2026-04-17  4:35   ` sashiko-bot
2026-04-18 17:10     ` Yonghong Song
2026-04-17  4:43   ` bot+bpf-ci
2026-04-18 17:11     ` Yonghong Song
2026-04-18  1:04   ` bot+bpf-ci
2026-04-17  3:47 ` [PATCH bpf-next v5 09/16] bpf: Reject stack arguments in non-JITed programs Yonghong Song
2026-04-17  4:30   ` bot+bpf-ci
2026-04-18 17:17     ` Yonghong Song
2026-04-18  0:52   ` bot+bpf-ci
2026-04-17  3:47 ` [PATCH bpf-next v5 10/16] bpf: Reject stack arguments if tail call reachable Yonghong Song
2026-04-17  4:08   ` sashiko-bot
2026-04-18 17:18     ` Yonghong Song
2026-04-18 17:37     ` Yonghong Song
2026-04-17  4:30   ` bot+bpf-ci
2026-04-18  1:04   ` bot+bpf-ci
2026-04-18 17:24     ` Yonghong Song
2026-04-17  3:47 ` [PATCH bpf-next v5 11/16] bpf: Support stack arguments for kfunc calls Yonghong Song
2026-04-17  4:40   ` sashiko-bot
2026-04-18 17:46     ` Yonghong Song
2026-04-17  4:43   ` bot+bpf-ci
2026-04-18 17:57     ` Yonghong Song
2026-04-18  1:04   ` bot+bpf-ci
2026-04-18 18:04     ` Yonghong Song
2026-04-17  3:47 ` [PATCH bpf-next v5 12/16] bpf: Enable stack argument support for x86_64 Yonghong Song
2026-04-17  4:30   ` bot+bpf-ci
2026-04-17  5:03   ` sashiko-bot
2026-04-18 18:07     ` Yonghong Song
2026-04-18  1:04   ` bot+bpf-ci
2026-04-17  3:48 ` [PATCH bpf-next v5 13/16] bpf,x86: Implement JIT support for stack arguments Yonghong Song
2026-04-17  4:44   ` sashiko-bot [this message]
2026-04-18 16:43     ` Puranjay Mohan
2026-04-18 18:15     ` Yonghong Song
2026-04-18  1:20   ` bot+bpf-ci
2026-04-18 18:23     ` Yonghong Song
2026-04-17  3:48 ` [PATCH bpf-next v5 14/16] selftests/bpf: Add tests for BPF function " Yonghong Song
2026-04-17  4:20   ` sashiko-bot
2026-04-18  0:52   ` bot+bpf-ci
2026-04-18 18:26     ` Yonghong Song
2026-04-17  3:48 ` [PATCH bpf-next v5 15/16] selftests/bpf: Add negative test for greater-than-8-byte kfunc stack argument Yonghong Song
2026-04-17  4:28   ` sashiko-bot
2026-04-18 18:29     ` Yonghong Song
2026-04-18  0:52   ` bot+bpf-ci
2026-04-17  3:48 ` [PATCH bpf-next v5 16/16] selftests/bpf: Add verifier tests for stack argument validation Yonghong Song
2026-04-17  4:38   ` sashiko-bot
2026-04-18 18:36     ` Yonghong Song
2026-04-18  0:52   ` bot+bpf-ci
2026-04-18 16:39 ` [PATCH bpf-next v5 00/16] bpf: Support stack arguments for BPF functions and kfuncs Puranjay Mohan
2026-04-18 18:47   ` Alexei Starovoitov
2026-04-18 18:54     ` Yonghong Song
2026-04-18 17:06 ` Puranjay Mohan

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=20260417044443.66D37C19425@smtp.kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=bpf@vger.kernel.org \
    --cc=sashiko@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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.