Re: [PATCH bpf-next 10/18] bpf,x86: Implement JIT support for stack arguments

Yonghong Song
2026-04-25T05:29:40Z

On 4/24/26 11:00 AM, bot+bpf-ci@kernel.org wrote:
>> diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c
>> index ea9e707e8abf..06f33fef1e8e 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_verifier_env *env, struct bpf_prog *bpf_prog, int *
>> int i, excnt = 0;
>> int ilen, proglen = 0;
>> u8 *ip, *prog = temp;
>> + u16 stack_arg_depth, incoming_stack_arg_depth, outgoing_stack_arg_depth;
>> + u16 outgoing_rsp;
>> u32 stack_depth;
>> + int callee_saved_size;
>> + s32 outgoing_arg_base;
>> int err;
>>
>> 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;
> ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>
> Can this underflow? All three variables are u16, so the subtraction
> wraps around modulo 65536.
>
> Looking at btf_prepare_func_args() in kernel/bpf/btf.c, it sets
> 'sub->incoming_stack_arg_depth = (nargs - MAX_BPF_FUNC_REG_ARGS) *
> BPF_REG_SIZE' for any static subprog with more than 5 arguments. It does
> not initialize sub->stack_arg_depth.
>
> The 'stack_arg_depth' field is only written by check_func_call() in
> kernel/bpf/verifier.c and check_kfunc_call(), which update the *caller's*
> subprog entry when the caller makes a call with more than 5 arguments.
>
> Since env->subprog_info[] is zero-initialized (kvcalloc), leaf subprograms
> that receive stack arguments but never call other functions with stack
> arguments will have:
> incoming_stack_arg_depth = (nargs - 5) * 8
> stack_arg_depth = 0
>
> For example:
> static int leaf(int a1, int a2, int a3, int a4, int a5, int a6, int a7)
> {
> return a1 + a7; /* r11+16 load, then BPF_EXIT - no calls */
> }
>
> /* some other subprog does: ret = leaf(1,2,3,4,5,6,7); */
>
> For 'leaf', the verifier sets:
> incoming_stack_arg_depth = (7 - 5) * 8 = 16
> stack_arg_depth = 0 (never updated, no calls made)
>
> When do_jit() computes:
> outgoing_stack_arg_depth = 0 - 16 = 0xFFF0 (u16 underflow)
>
> Then at the new code below:
>
>> + /*
>> + * Allocate outgoing stack arg area for args 7+ only.
>> + * Arg 6 goes into r9 register, not on stack.
>> + */
>> + outgoing_rsp = outgoing_stack_arg_depth > 8 ? outgoing_stack_arg_depth - 8 : 0;
> ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>> + emit_sub_rsp(&prog, outgoing_rsp);
> This emits 'sub rsp, 0xFFE8' (about 65 KB), which overflows the kernel
> stack (THREAD_SIZE is only 16 KB on x86_64). The epilogue then emits a
> matching 'add rsp, 0xFFE8', but the damage is already done at function
> entry.
>
> The commit message states "The verifier guarantees that neither
> tail_call_reachable nor priv_stack is set when stack args exist, so R9 is
> always available." It does not claim the verifier maintains
> 'stack_arg_depth >= incoming_stack_arg_depth', and that invariant is not
> maintained for leaf subprograms.
>
> The sanity check in bpf_fixup_call_args() at kernel/bpf/fixups.c does not
> catch this because the same underflow happens there:
> u16 outgoing = subprog->stack_arg_depth - subprog->incoming_stack_arg_depth;
> but since leaf subprograms have max_out_stack_arg_depth == 0, the
> comparison 'outgoing > max_out_stack_arg_depth' is false (0xFFF0 wraps
> around in the comparison).
>
> Should the JIT compute outgoing_stack_arg_depth safely to prevent the
> underflow? For example:
> outgoing_stack_arg_depth = stack_arg_depth > incoming_stack_arg_depth ?
> stack_arg_depth - incoming_stack_arg_depth : 0;
>
> Or should the verifier ensure the invariant 'stack_arg_depth >=
> incoming_stack_arg_depth' after verification completes?

You are right! I missed this case where the caller signature has more
than 5 arguments and the caller itself does not have any callee's.
This caused the problem as you mentioned above. I will fix the issue
and added a selftest for this 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/24902767240