Re: [PATCH v4 1/5] powerpc/bpf: fix alignment of long branch trampoline address
From: bot+bpf-ci@kernel.org
Date: 2026-05-17 18:30:22
Also in:
linux-kselftest, linuxppc-dev, stable
quoted hunk ↗ jump to hunk
diff --git a/arch/powerpc/net/bpf_jit.h b/arch/powerpc/net/bpf_jit.h index f32de8704d4d..71e6e7d01057 100644 --- a/arch/powerpc/net/bpf_jit.h +++ b/arch/powerpc/net/bpf_jit.h@@ -214,8 +214,8 @@ int bpf_jit_emit_func_call_rel(u32 *image, u32 *fimage, struct codegen_context * int bpf_jit_build_body(struct bpf_prog *fp, u32 *image, u32 *fimage, struct codegen_context *ctx, u32 *addrs, int pass, bool extra_pass); void bpf_jit_build_prologue(u32 *image, struct codegen_context *ctx); -void bpf_jit_build_epilogue(u32 *image, struct codegen_context *ctx); -void bpf_jit_build_fentry_stubs(u32 *image, struct codegen_context *ctx); +void bpf_jit_build_epilogue(u32 *image, u32 *fimage, struct codegen_context *ctx); +void bpf_jit_build_fentry_stubs(u32 *image, u32 *fimage, struct codegen_context *ctx); void bpf_jit_realloc_regs(struct codegen_context *ctx); int bpf_jit_emit_exit_insn(u32 *image, struct codegen_context *ctx, int tmp_reg, long exit_addr); void prepare_for_fsession_fentry(u32 *image, struct codegen_context *ctx, int cookie_cnt,
The header file arch/powerpc/net/bpf_jit.h is shared by both the 64-bit (bpf_jit_comp64.c) and 32-bit (bpf_jit_comp32.c) BPF JIT compilers (per arch/powerpc/net/Makefile). The patch updates these prototypes to add a new 'u32 *fimage' parameter, and modifies the PPC64 implementation (bpf_jit_comp64.c) and the shared file (bpf_jit_comp.c) accordingly. However, arch/powerpc/net/bpf_jit_comp32.c is not updated. In that file, bpf_jit_build_epilogue() still has the 2-argument signature: void bpf_jit_build_epilogue(u32 *image, struct codegen_context *ctx) and its call to bpf_jit_build_fentry_stubs() passes only 2 arguments: bpf_jit_build_fentry_stubs(image, ctx); Will this cause a function signature conflict under CONFIG_PPC32 builds (CONFIG_PPC_BOOK3S_32, CONFIG_PPC_8xx, etc.) since the header now declares the 3-argument prototype while the .c file defines the 2-argument version?
quoted hunk ↗ jump to hunk
diff --git a/arch/powerpc/net/bpf_jit_comp.c b/arch/powerpc/net/bpf_jit_comp.c index 53ab97ad6074..ef7614177cb1 100644 --- a/arch/powerpc/net/bpf_jit_comp.c +++ b/arch/powerpc/net/bpf_jit_comp.c@@ -49,11 +49,34 @@ asm ( " .popsection ;" ); -void bpf_jit_build_fentry_stubs(u32 *image, struct codegen_context *ctx) +void bpf_jit_build_fentry_stubs(u32 *image, u32 *fimage, struct codegen_context *ctx) { int ool_stub_idx, long_branch_stub_idx; /* + * In the final pass, align the mis-aligned dummy_tramp_addr field + * in the fimage. The alignment NOP must appear before OOL stub, + * to make ool_stub_idx & long_branch_stub_idx constant from end. + */ +#ifdef CONFIG_PPC64 + if (fimage && image) {
During pass 0 (where fimage and image are NULL), this condition evaluates to false. The alignment NOP is not counted in proglen during size calculation. During the final passes (1 and 2), if the NOP is emitted, could this increase the instruction count beyond proglen and overflow into the subsequent exception table or fixups?
+ /* + * pc points to first instruction of OOL stub, + * dummy_tramp_addr is past 4/3 instructions depending on + * CONFIG_PPC_FTRACE_OUT_OF_LINE is enabled/not respectively. + * + * The decision to emit alignment NOP must depend on the alignment + * of dummy_tramp_addr field. + */ + unsigned long pc = (unsigned long)fimage + CTX_NIA(ctx); + pc += IS_ENABLED(CONFIG_PPC_FTRACE_OUT_OF_LINE) ? 4 : 3; + + if (!IS_ALIGNED(pc, 8)) + EMIT(PPC_RAW_NOP()); + }
The alignment calculation appears to be incorrect. The code adds 4 or 3 to the pc value, which is a byte address. Since PowerPC instructions are 4 bytes each, adding 4 or 3 bytes gives the wrong offset. Looking at the OOL stub instructions that follow this block, with CONFIG_PPC_FTRACE_OUT_OF_LINE there are 4 instructions (mflr r0; nop; mtlr r0; b bpf_func+4). This produces a 16-byte offset (4 instructions * 4 bytes). Without the config, there are 3 instructions producing a 12-byte offset. The dummy_tramp_addr field would therefore be at pc+16 or pc+12, not pc+4 or pc+3. For example, with CONFIG_PPC_FTRACE_OUT_OF_LINE enabled and pc 8-byte aligned (pc%8 == 0): - True dummy_tramp_addr position: pc+16, which is (pc+16)%8 == 0, already aligned. - But the code calculates: pc += 4 -> pc+4, then !IS_ALIGNED(pc+4, 8) is true -> emits NOP. - With the NOP, dummy_tramp_addr ends up at pc+4+16 = pc+20, and (pc+20)%8 == 4, which is misaligned. Similarly, when pc%8 == 4: - True dummy_tramp_addr position: pc+16, which is (pc+16)%8 == 4, not aligned. - But the code calculates: pc += 4 -> pc+4, then IS_ALIGNED(pc+4, 8) is true -> skips NOP. - dummy_tramp_addr remains at pc+16, which is misaligned. Does this flawed arithmetic force the code to emit a NOP when the target address is already aligned, thereby misaligning it instead of aligning it?
quoted hunk ↗ jump to hunk
@@ -107,7 +131,7 @@ int bpf_jit_emit_exit_insn(u32 *image, struct codegen_context *ctx, int tmp_reg, PPC_JMP(ctx->alt_exit_addr); } else { ctx->alt_exit_addr = ctx->idx * 4; - bpf_jit_build_epilogue(image, ctx); + bpf_jit_build_epilogue(image, NULL, ctx); }
Because fimage is strictly passed as NULL here, the if (fimage && image) check in bpf_jit_build_fentry_stubs() will always evaluate to false. Will this cause the alignment NOP to be unconditionally skipped for all inline epilogues, leaving their dummy_tramp_addr fields unaligned? [ ... ]
quoted hunk ↗ jump to hunk
diff --git a/arch/powerpc/net/bpf_jit_comp64.c b/arch/powerpc/net/bpf_jit_comp64.c index db364d9083e7..885dc8cf55a2 100644 --- a/arch/powerpc/net/bpf_jit_comp64.c +++ b/arch/powerpc/net/bpf_jit_comp64.c@@ -398,7 +398,7 @@ static void bpf_jit_emit_common_epilogue(u32 *image, struct codegen_context *ctx } } -void bpf_jit_build_epilogue(u32 *image, struct codegen_context *ctx) +void bpf_jit_build_epilogue(u32 *image, u32 *fimage, struct codegen_context *ctx) { bpf_jit_emit_common_epilogue(image, ctx);@@ -407,7 +407,7 @@ void bpf_jit_build_epilogue(u32 *image, struct codegen_context *ctx) EMIT(PPC_RAW_BLR()); - bpf_jit_build_fentry_stubs(image, ctx); + bpf_jit_build_fentry_stubs(image, fimage, ctx); }
--- 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/25998434343