> diff --git a/arch/powerpc/net/bpf_jit_comp.c b/arch/powerpc/net/bpf_jit_comp.c
> index 52162e4a7f84..9c27740650b5 100644
> --- a/arch/powerpc/net/bpf_jit_comp.c
> +++ b/arch/powerpc/net/bpf_jit_comp.c
> @@ -318,6 +318,12 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *fp)
>               jit_data->hdr = hdr;
>       }
>
> +     /*
> +      * The bpf_prog_update_insn_ptrs function expects addrs to
> +      * point to the first byte of the jitted instruction.
> +      */
> +     bpf_prog_update_insn_ptrs(fp, addrs, fimage);

Is addrs still valid at this point?  Looking at the code above, in the
final-pass path where (!fp->is_func || extra_pass) is true, addrs has
already been freed:

bpf_int_jit_compile() {
    ...
    if (!fp->is_func || extra_pass) {
        ...
        bpf_prog_fill_jited_linfo(fp, addrs);
out_addrs:
        kfree(addrs);
        kfree(jit_data);
        fp->aux->jit_data = NULL;
    } else {
        jit_data->addrs = addrs;
        ...
        jit_data->hdr = hdr;
    }

    bpf_prog_update_insn_ptrs(fp, addrs, fimage);  /* <-- here */
    ...
}

The kfree(addrs) happens before this call.  The NULL check inside
bpf_prog_update_insn_ptrs() does not catch this because kfree()
does not set the pointer to NULL, so offsets[xlated_off] would read
from freed memory.

The x86 JIT avoids this by placing bpf_prog_update_insn_ptrs() inside
the if (image) block before the addrs are freed:

arch/x86/net/bpf_jit_comp.c:bpf_int_jit_compile() {
    ...
    bpf_prog_update_insn_ptrs(prog, addrs, image);
    ...
    /* addrs freed later */
    kvfree(addrs);
}

Should this call be moved before the out_addrs label, similar to
how x86 does it?

Additionally, for CONFIG_PPC64_ELF_ABI_V1 where FUNCTION_DESCR_SIZE
is 24, the addrs offsets are relative to code_base, not fimage:

    code_base = (u32 *)(image + FUNCTION_DESCR_SIZE);
    fcode_base = (u32 *)(fimage + FUNCTION_DESCR_SIZE);

Would the image argument need to be (fimage + FUNCTION_DESCR_SIZE)
rather than fimage to produce the correct absolute addresses in
insn_array->ips[]?

>  out:
>       if (bpf_blinded)
>               bpf_jit_prog_release_other(fp, fp == org_fp ? tmp_fp : org_fp);

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

AI-authorship-score: low
AI-authorship-explanation: Standard kernel patch conventions with specific 
upstream references; no AI-generation indicators.
issues-found: 2
issue-severity-score: high
issue-severity-explanation: Use-after-free on addrs array in normal JIT success 
path can corrupt insn_array jump targets, leading to crashes or undefined 
behavior.

Reply via email to