> diff --git a/arch/powerpc/net/bpf_jit_comp64.c 
> b/arch/powerpc/net/bpf_jit_comp64.c
> index a6083dd9786c..941e0818c9ec 100644
> --- a/arch/powerpc/net/bpf_jit_comp64.c
> +++ b/arch/powerpc/net/bpf_jit_comp64.c

[ ... ]

> @@ -103,9 +119,12 @@ static inline bool bpf_has_stack_frame(struct 
> codegen_context *ctx)
>  *            [         ...           ]               |
>  * sp (r1) --->       [    stack pointer      ] --------------
>  *            [    tail_call_info     ] 8
> - *           [   nv gpr save area    ] 6*8
> + *           [   nv gpr save area    ] 6*8 + (12*8)
>  *            [    local_tmp_var      ] 24
>  *            [   unused red zone     ] 224
> + *
> + * Additional (12*8) in 'nv gpr save area' only in case of
> + * exception boundary.
>  */
>  static int bpf_jit_stack_local(struct codegen_context *ctx)
>  {
> @@ -114,7 +133,11 @@ static int bpf_jit_stack_local(struct codegen_context 
> *ctx)
>               return STACK_FRAME_MIN_SIZE + ctx->stack_size;

Does this need to account for BPF_PPC_EXC_STACK_SAVE when
exception_boundary or exception_cb is true?

In the else branch below, the exception case is handled, but the
bpf_has_stack_frame() case returns the same value regardless of
exception_boundary. However, bpf_jit_build_prologue() creates a larger
frame using BPF_PPC_EXC_STACKFRAME when exception_boundary is true.

This inconsistency appears to cause bpf_jit_stack_tailcallinfo_offset()
to return an incorrect offset when both bpf_has_stack_frame() returns
true AND exception_boundary is true. The offset would be off by 96 bytes
(BPF_PPC_EXC_STACK_SAVE).

For example, if a program uses bpf_throw (setting exception_boundary=true)
and also calls helper functions (setting SEEN_FUNC, making
bpf_has_stack_frame() return true), and uses tail calls, the tail call
handling in bpf_jit_emit_tail_call() would access the wrong stack location.

>       } else {
>               /* Stack layout 2 */
> -             return -(BPF_PPC_TAILCALL + BPF_PPC_STACK_SAVE + 
> BPF_PPC_STACK_LOCALS);
> +             return -(BPF_PPC_TAILCALL
> +                     + BPF_PPC_STACK_SAVE
> +                     + (ctx->exception_boundary || ctx->exception_cb ?
> +                                                     
> BPF_PPC_EXC_STACK_SAVE:0)
> +                     + BPF_PPC_STACK_LOCALS);
>       }
>  }

[ ... ]

> @@ -189,7 +222,20 @@ void bpf_jit_build_prologue(u32 *image, struct 
> codegen_context *ctx)
>                       EMIT(PPC_RAW_STD(_R0, _R1, PPC_LR_STKOFF));
>               }
>
> -             EMIT(PPC_RAW_STDU(_R1, _R1, -(BPF_PPC_STACKFRAME + 
> ctx->stack_size)));
> +             int stack_expand = ctx->exception_boundary || ctx->exception_cb 
> ?
> +                                     BPF_PPC_EXC_STACKFRAME : 
> BPF_PPC_STACKFRAME;
> +             EMIT(PPC_RAW_STDU(_R1, _R1, -(stack_expand + ctx->stack_size)));

The stack frame expansion here uses BPF_PPC_EXC_STACKFRAME for exception
cases, but bpf_jit_stack_local() in the bpf_has_stack_frame() branch does
not account for this larger frame size.

[ ... ]


---
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/20993216190

Reply via email to