Naveen N. Rao writes: > Since BPF constant blinding is performed after the verifier pass, the > ALU32 instructions inserted for doubleword immediate loads don't have a > corresponding zext instruction. This is causing a kernel oops on powerpc > and can be reproduced by running 'test_cgroup_storage' with > bpf_jit_harden=2. > > Fix this by emitting BPF_ZEXT during constant blinding if > prog->aux->verifier_zext is set. > > Fixes: a4b1d3c1ddf6cb ("bpf: verifier: insert zero extension according to analysis result") > Reported-by: Michael Ellerman <mpe@xxxxxxxxxxxxxx> > Signed-off-by: Naveen N. Rao <naveen.n.rao@xxxxxxxxxxxxxxxxxx> Thanks for the fix. Reviewed-by: Jiong Wang <jiong.wang@xxxxxxxxxxxxx> Just two other comments during review in case I am wrong on somewhere. - Use verifier_zext instead of bpf_jit_needs_zext() seems better, even though the latter could avoid extending function argument. Because JIT back-ends look at verifier_zext, true means zext inserted by verifier so JITs won't do the code-gen. Use verifier_zext is sort of keeping JIT blinding the same behaviour has verifier even though blinding doesn't belong to verifier, but for such insn patching, it could be seen as a extension of verifier, therefore use verifier_zext seems better than bpf_jit_needs_zext() to me. - JIT blinding is also escaping the HI32 randomization which happens inside verifier, otherwise x86-64 regression should have caught this issue. Regards, Jiong > --- > Changes since RFC: > - Removed changes to ALU32 and JMP32 ops since those don't alter program > execution, and the verifier would have already accounted for them. > > > kernel/bpf/core.c | 8 ++++++-- > 1 file changed, 6 insertions(+), 2 deletions(-) > > diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c > index 8191a7db2777..66088a9e9b9e 100644 > --- a/kernel/bpf/core.c > +++ b/kernel/bpf/core.c > @@ -890,7 +890,8 @@ int bpf_jit_get_func_addr(const struct bpf_prog *prog, > > static int bpf_jit_blind_insn(const struct bpf_insn *from, > const struct bpf_insn *aux, > - struct bpf_insn *to_buff) > + struct bpf_insn *to_buff, > + bool emit_zext) > { > struct bpf_insn *to = to_buff; > u32 imm_rnd = get_random_int(); > @@ -1005,6 +1006,8 @@ static int bpf_jit_blind_insn(const struct bpf_insn *from, > case 0: /* Part 2 of BPF_LD | BPF_IMM | BPF_DW. */ > *to++ = BPF_ALU32_IMM(BPF_MOV, BPF_REG_AX, imm_rnd ^ aux[0].imm); > *to++ = BPF_ALU32_IMM(BPF_XOR, BPF_REG_AX, imm_rnd); > + if (emit_zext) > + *to++ = BPF_ZEXT_REG(BPF_REG_AX); > *to++ = BPF_ALU64_REG(BPF_OR, aux[0].dst_reg, BPF_REG_AX); > break; > > @@ -1088,7 +1091,8 @@ struct bpf_prog *bpf_jit_blind_constants(struct bpf_prog *prog) > insn[1].code == 0) > memcpy(aux, insn, sizeof(aux)); > > - rewritten = bpf_jit_blind_insn(insn, aux, insn_buff); > + rewritten = bpf_jit_blind_insn(insn, aux, insn_buff, > + clone->aux->verifier_zext); > if (!rewritten) > continue;