> 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