public inbox for bpf@vger.kernel.org
 help / color / mirror / Atom feed
From: Yonghong Song <yonghong.song@linux.dev>
To: sashiko@lists.linux.dev
Cc: bpf@vger.kernel.org
Subject: Re: [PATCH bpf-next v6 07/17] bpf: Support stack arguments for bpf functions
Date: Sun, 19 Apr 2026 21:35:57 -0700	[thread overview]
Message-ID: <961513ff-b3ba-4d27-b568-071a7c68e53f@linux.dev> (raw)
In-Reply-To: <20260419191516.44EA1C2BCAF@smtp.kernel.org>



On 4/19/26 12:15 PM, sashiko-bot@kernel.org wrote:
> Sashiko AI review found 3 potential issue(s):
> - [Critical] Missing precision tracking for stack arguments (`BPF_REG_PARAMS` / `r11`) leads to incorrect verifier state pruning and arbitrary out-of-bounds memory access.
> - [Medium] `BPF_PROG_TYPE_EXT` (freplace) programs are incorrectly rejected when targeting static subprograms with more than 5 arguments.
> - [Low] `stack_arg_safe()` strictly compares `stack_arg_depth`, preventing safe paths from being pruned and leading to state explosion.
> --
>
> commit 0c58d1bb907c4a6a387f1afd22baae9d43e95a55
> Author: Yonghong Song <yonghong.song@linux.dev>
> Subject: bpf: Support stack arguments for bpf functions
>
> This commit introduces support for passing more than 5 arguments to BPF
> subprograms by using a dedicated stack area accessed via register r11.
> It tracks these stack arguments separately from the regular stack to ensure
> proper verification and pruning.
>
> Link: https://github.com/llvm/llvm-project/pull/189060
>
>> diff --git a/kernel/bpf/states.c b/kernel/bpf/states.c
>> index 8478d2c6ed5b6..235841d23fe3f 100644
>> --- a/kernel/bpf/states.c
>> +++ b/kernel/bpf/states.c
> [ ... ]
>> @@ -838,6 +838,44 @@ static bool stacksafe(struct bpf_verifier_env *env, struct bpf_func_state *old,
>>   	return true;
>>   }
>>   
>> +/*
>> + * Compare stack arg slots between old and current states.
>> + * Outgoing stack args are path-local state and must agree for pruning.
>> + */
>> +static bool stack_arg_safe(struct bpf_verifier_env *env, struct bpf_func_state *old,
>> +			   struct bpf_func_state *cur, struct bpf_idmap *idmap,
>> +			   enum exact_level exact)
>> +{
>> +	int i, nslots;
>> +
>> +	if (old->incoming_stack_arg_depth != cur->incoming_stack_arg_depth)
>> +		return false;
>> +
>> +	/* Compare both incoming and outgoing stack arg slots. */
>> +	if (old->stack_arg_depth != cur->stack_arg_depth)
>> +		return false;
> Does this strict comparison of stack_arg_depth prevent safe paths from
> being pruned?
>
> Since stack_arg_depth tracks the allocated capacity rather than the
> active outgoing arguments tracked by out_stack_arg_mask, two branches
> that call subprograms with different stack argument requirements might
> end up with permanently different stack_arg_depth values.
>
> Could this unnecessarily increase verification complexity by failing to
> prune functionally equivalent states?

You are right. We should not compare stack_arg_depth, which is not tracking
arguments. The out_stack_arg_mask is the correct way to do comparison.

>
> [ ... ]
>> diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
>> index 6aa4dc161a563..78c9322870a51 100644
>> --- a/kernel/bpf/verifier.c
>> +++ b/kernel/bpf/verifier.c
> [ ... ]
>> +static int check_stack_arg_write(struct bpf_verifier_env *env, struct bpf_func_state *state,
>> +				 int off, int value_regno)
>> +{
>> +	int max_stack_arg_regs = MAX_BPF_FUNC_ARGS - MAX_BPF_FUNC_REG_ARGS;
> [ ... ]
>> +	state->out_stack_arg_mask |= BIT(idx);
>> +	return 0;
>> +}
>> +
>> +/*
>> + * Read a value from the incoming stack arg area.
>> + * off is a positive offset from r11 (e.g. +8 for arg6, +16 for arg7).
>> + * Callers ensure off > 0, 8-byte aligned, and size is BPF_REG_SIZE.
>> + */
>> +static int check_stack_arg_read(struct bpf_verifier_env *env, struct bpf_func_state *state,
>> +				int off, int dst_regno)
>> +{
> [ ... ]
>> +	if (is_spillable_regtype(arg->type))
>> +		copy_register_state(&cur->regs[dst_regno], arg);
>> +	else
>> +		mark_reg_unknown(env, cur->regs, dst_regno);
>> +	return 0;
>> +}
> Should check_stack_arg_read() and check_stack_arg_write() call
> bpf_push_jmp_history() with the INSN_F_STACK_ACCESS flag?
>
> When the callee uses a stack argument in a context requiring precision,
> backtracking is initiated. Because the INSN_F_STACK_ACCESS flag is
> missing, backtrack_insn() might silently return 0. This clears the
> destination register without propagating the precision requirement to
> the stack slot.
>
> Could this cause the verifier to incorrectly prune execution paths
> containing different, potentially unsafe scalar values, allowing
> programs to bypass verifier bounds checks and perform arbitrary
> out-of-bounds accesses? Note that the subsequent patch that tracks
> r11 registers in const_fold and liveness does not address this
> backtracking logic.

Yes, you are right. I will think of how to get backtracking work
for check_stack_arg_read() and check_stack_arg_write().

>
> [ ... ]
>> @@ -18808,7 +19097,7 @@ static int do_check_common(struct bpf_verifier_env *env, int subprog)
>>   				goto out;
>>   			}
>>   		}
>> -		for (i = BPF_REG_1; i <= sub->arg_cnt; i++) {
>> +		for (i = BPF_REG_1; i <= min_t(u32, sub->arg_cnt, MAX_BPF_FUNC_REG_ARGS); i++) {
>>   			arg = &sub->args[i - BPF_REG_1];
>>   			reg = &regs[i];
> For freplace programs targeting static subprograms with more than 5
> arguments, do we need to initialize state->frame[0]->incoming_stack_arg_depth
> here or allocate stack_arg_regs?
>
> Currently it seems to only initialize arguments up to MAX_BPF_FUNC_REG_ARGS.
> If incoming_stack_arg_depth remains 0, an EXT program attempting to read
> its 6th argument via BPF_REG_PARAMS would fail verification in
> check_stack_arg_read() with -EACCES.

For freplace, considering the patch set is always very big, I would like
to delay this. I will add a check for freplace. If it has more than 5
parameters, will cause verification failure.


  reply	other threads:[~2026-04-20  4:36 UTC|newest]

Thread overview: 51+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-04-19 16:33 [PATCH bpf-next v6 00/17] bpf: Support stack arguments for BPF functions and kfuncs Yonghong Song
2026-04-19 16:33 ` [PATCH bpf-next v6 01/17] bpf: Remove unused parameter from check_map_kptr_access() Yonghong Song
2026-04-19 16:33 ` [PATCH bpf-next v6 02/17] bpf: Refactor to avoid redundant calculation of bpf_reg_state Yonghong Song
2026-04-19 16:33 ` [PATCH bpf-next v6 03/17] bpf: Refactor to handle memory and size together Yonghong Song
2026-04-20 23:58   ` Alexei Starovoitov
2026-04-21  4:04     ` Yonghong Song
2026-04-19 16:33 ` [PATCH bpf-next v6 04/17] bpf: Prepare verifier logs for upcoming kfunc stack arguments Yonghong Song
2026-04-21  0:03   ` Alexei Starovoitov
2026-04-21  4:06     ` Yonghong Song
2026-04-21  6:07     ` Yonghong Song
2026-04-21 13:48       ` Alexei Starovoitov
2026-04-21 15:41         ` Yonghong Song
2026-04-21 15:46           ` Alexei Starovoitov
2026-04-21 16:37             ` Yonghong Song
2026-04-21 17:24             ` Yonghong Song
2026-04-19 16:33 ` [PATCH bpf-next v6 05/17] bpf: Introduce bpf register BPF_REG_PARAMS Yonghong Song
2026-04-19 17:06   ` sashiko-bot
2026-04-19 18:14     ` Yonghong Song
2026-04-19 16:33 ` [PATCH bpf-next v6 06/17] bpf: Reuse MAX_BPF_FUNC_ARGS for maximum number of arguments Yonghong Song
2026-04-19 16:33 ` [PATCH bpf-next v6 07/17] bpf: Support stack arguments for bpf functions Yonghong Song
2026-04-19 19:15   ` sashiko-bot
2026-04-20  4:35     ` Yonghong Song [this message]
2026-04-21  0:37   ` Alexei Starovoitov
2026-04-21  4:15     ` Yonghong Song
2026-04-19 16:33 ` [PATCH bpf-next v6 08/17] bpf: Reject stack arguments in non-JITed programs Yonghong Song
2026-04-19 18:21   ` sashiko-bot
2026-04-20  4:23     ` Yonghong Song
2026-04-19 16:34 ` [PATCH bpf-next v6 09/17] bpf: Track r11 registers in const_fold and liveness Yonghong Song
2026-04-19 16:34 ` [PATCH bpf-next v6 10/17] bpf: Prepare architecture JIT support for stack arguments Yonghong Song
2026-04-19 16:34 ` [PATCH bpf-next v6 11/17] bpf: Enable r11 based insns Yonghong Song
2026-04-19 16:34 ` [PATCH bpf-next v6 12/17] bpf: Support stack arguments for kfunc calls Yonghong Song
2026-04-19 17:08   ` sashiko-bot
2026-04-19 18:18     ` Yonghong Song
2026-04-19 16:34 ` [PATCH bpf-next v6 13/17] bpf: Reject stack arguments if tail call reachable Yonghong Song
2026-04-19 17:08   ` sashiko-bot
2026-04-19 18:20     ` Yonghong Song
2026-04-19 16:34 ` [PATCH bpf-next v6 14/17] bpf,x86: Implement JIT support for stack arguments Yonghong Song
2026-04-19 17:25   ` sashiko-bot
2026-04-19 18:55     ` Yonghong Song
2026-04-19 16:34 ` [PATCH bpf-next v6 15/17] selftests/bpf: Add tests for BPF function " Yonghong Song
2026-04-19 17:15   ` sashiko-bot
2026-04-20  5:52     ` Yonghong Song
2026-04-19 16:34 ` [PATCH bpf-next v6 16/17] selftests/bpf: Add tests for stack argument validation Yonghong Song
2026-04-19 16:34 ` [PATCH bpf-next v6 17/17] selftests/bpf: Add verifier " Yonghong Song
2026-04-19 17:21   ` sashiko-bot
2026-04-20  6:14     ` Yonghong Song
2026-04-20 15:41 ` [PATCH bpf-next v6 00/17] bpf: Support stack arguments for BPF functions and kfuncs Puranjay Mohan
2026-04-20 20:22   ` Yonghong Song
2026-04-20 20:25     ` Puranjay Mohan
2026-04-20 21:49       ` Alexei Starovoitov
2026-04-20 23:44         ` 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=961513ff-b3ba-4d27-b568-071a7c68e53f@linux.dev \
    --to=yonghong.song@linux.dev \
    --cc=bpf@vger.kernel.org \
    --cc=sashiko@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