> selftest/bpf: Fixing powerpc JIT disassembly failure
>
> Ensure that the trampoline stubs JITed at the tail of the
> epilogue do not expose the dummy trampoline address stored
> in the last 8 bytes(64-bit) and last 4 bytes(32-bit)
> to the disassembly flow. Prevent the disassembler from
> ingesting this memory address, as it may occasionally decode
> into a seemingly valid but incorrect instruction. Fix this
> issue by truncating the last 8/4 bytes from JITed buffers
> before supplying them for disassembly.
>
> Fixes: b991fc520700 ("selftests/bpf: utility function to get program 
> disassembly after jit")

The Fixes: tag names b991fc520700 ("selftests/bpf: utility function to get
program disassembly after jit", 2024-08-21), which is the commit that
introduced get_jited_program_text() itself. That helper was not wrong when
written: at that time no powerpc JIT emitted a raw data word inside a
program, and the helper is documented (jit_disasm_helpers.c:13) as serving
small assembly test programs.

The undisassemblable trailing bytes come from d243b62b7bd3 ("powerpc64/bpf:
Add support for bpf trampolines", 2024-10-31) - the same commit both
sibling patches in this series cite - and only become observable once
powerpc jited selftests are enabled, which happens later in this series in
d3841599dc7ca ("selftest/bpf: Enable verifier selftest for powerpc64").

More importantly, the fix as written is only correct on top of its
immediate parent. Truncating the last trunc_len bytes assumes
dummy_tramp_addr is the final thing in the JITed image. That layout is
established by the immediate parent c6ba4edfe6e46 ("powerpc/bpf: Move out
dummy_tramp_addr after Long branch stub"), which moved the data word from
the top of the long branch stub to its bottom:

arch/powerpc/net/bpf_jit_comp.c:bpf_jit_build_fentry_stubs() {
    ...
    long_branch_stub_idx = ctx->idx;
    EMIT(PPC_RAW_MFLR(_R11));
    ...
    EMIT(PPC_RAW_BCTR());

    if (image)
            *((unsigned long *)&image[ctx->idx]) = (unsigned long)dummy_tramp;

    ctx->idx += SZL / 4;
}

On any tree that has b991fc520700 but not c6ba4edfe6e46, dummy_tramp_addr
sits before the seven long-branch instructions, so trimming the tail
removes two real instructions (bctr and mtlr r11 on 64-bit) while leaving
the data word in the middle of the disassembled range - the disassembly
failure this patch targets is not fixed, and expected __jited() output is
silently altered.

A backport driven by the stated Fixes: tag alone would therefore land a
change that does not work. Should the tag point at the commit that
introduced the byte pattern (d243b62b7bd3), or should the dependency on
c6ba4edfe6e46 be stated explicitly in the changelog?

> diff --git a/tools/testing/selftests/bpf/jit_disasm_helpers.c 
> b/tools/testing/selftests/bpf/jit_disasm_helpers.c
> index 3558fe10e28cf..c4aa1d69d3bbf 100644
> --- a/tools/testing/selftests/bpf/jit_disasm_helpers.c
> +++ b/tools/testing/selftests/bpf/jit_disasm_helpers.c

[ ... ]

> @@ -225,9 +227,30 @@ int get_jited_program_text(int fd, char *text, size_t 
> text_sz)
>       if (!ASSERT_OK(err, "bpf_prog_get_info_by_fd #2"))
>               goto out;
>
> +     /*
> +      * last 8 bytes contains dummy_trampoline address in JIT
> +      * output on 64-bit and last 4 bytes on 32-bit powerpc,
> +      * which can't disassemble to a valid instruction.
> +      */

This isn't a bug, but the comment says the trailing bytes "can't
disassemble to a valid instruction", while the changelog for the same
change says the opposite - "it may occasionally decode into a seemingly
valid but incorrect instruction" - which is the case that actually
motivates unconditional truncation rather than tolerating a disasm
failure.

The comment also names the field "dummy_trampoline", whereas the arch code
calls the symbol "dummy_tramp" and the field "dummy_tramp_addr"
(arch/powerpc/net/bpf_jit_comp.c:118), so grepping from the comment does
not lead to the code.

Separately, the second added comment, "Disabled JIT have zero func_lens,
hence underflow", is a sentence fragment that leaves the reader to infer
that the ternary exists to avoid a __u32 wrap when func_lens[i] is 0.

Could this comment use the "dummy_tramp_addr" name from the arch code and
describe the failure the same way the changelog does, so the two do not
read as contradictory?

> +     triple = LLVMGetDefaultTargetTriple();
> +     if (triple) {
> +             if (strstr(triple, "powerpc64") || strstr(triple, "ppc64"))
> +                     trunc_len = 8;
> +             else if (strstr(triple, "powerpc") || strstr(triple, "ppc"))
> +                     trunc_len = 4;
> +             LLVMDisposeMessage(triple);
> +     }
> +
>       for (pc = 0, i = 0; i < jited_funcs; ++i) {
> +
>               fprintf(text_out, "func #%d:\n", i);

[ ... ]

> +
>               fprintf(text_out, "\n");
>               pc += func_lens[i];
>       }

This isn't a bug, but two blank lines are added inside the loop body that
are unrelated to the fix: one immediately after the "for (...) {" opening
brace, and one between the disasm_one_func() call and the following
fprintf(). Neither separates logical blocks - the loop body is six lines -
and no other loop in this file opens with a blank line (compare the two
"while (pc < len)" loops in disasm_one_func(), which start directly with
their first statement).

Are the two new blank lines inside this loop intentional, or could the
hunk stay limited to the truncation change?

> selftest/bpf: Fixing powerpc JIT disassembly failure

This isn't a bug, but the subject uses the prefix "selftest/bpf:"
(singular) where the tree's overwhelmingly dominant prefix for this
directory is "selftests/bpf:" - 1272 commits versus 10 in recent history.
The subject also uses the gerund "Fixing" rather than the imperative mood
the submitting-patches guidance asks for ("Fix ..." / "Skip ...").

Would "selftests/bpf: Skip trailing trampoline address bytes when
disassembling" fit the usual prefix and imperative style for this
directory better?


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

Reply via email to