bpf, ppc64: fix unexpected r0=0 exit path inside bpf_xadd
None of the JITs is allowed to implement exit paths from the BPF insn mappings other than BPF_JMP | BPF_EXIT. In the BPF core code we have a couple of rewrites in eBPF (e.g. LD_ABS / LD_IND) and in eBPF to cBPF translation to retain old existing behavior where exceptions may occur; they are also tightly controlled by the verifier where it disallows some of the features such as BPF to BPF calls when legacy LD_ABS / LD_IND ops are present in the BPF program. During recent review of all BPF_XADD JIT implementations I noticed that the ppc64 one is buggy in that it contains two jumps to exit paths. This is problematic as this can bypass verifier expectations e.g. pointed out in commitf6b1b3bf0d
("bpf: fix subprog verifier bypass by div/mod by 0 exception"). The first exit path is obsoleted by the fix inca36960211
("bpf: allow xadd only on aligned memory") anyway, and for the second one we need to do a fetch, add and store loop if the reservation from lwarx/ldarx was lost in the meantime. Fixes:156d0e290e
("powerpc/ebpf/jit: Implement JIT compiler for extended BPF") Reviewed-by: Naveen N. Rao <naveen.n.rao@linux.vnet.ibm.com> Reviewed-by: Sandipan Das <sandipan@linux.vnet.ibm.com> Tested-by: Sandipan Das <sandipan@linux.vnet.ibm.com> Signed-off-by: Daniel Borkmann <daniel@iogearbox.net> Signed-off-by: Alexei Starovoitov <ast@kernel.org>
This commit is contained in:
parent
f39f28ff82
commit
b9c1e60e7b
1 changed files with 5 additions and 24 deletions
|
@ -286,6 +286,7 @@ static int bpf_jit_build_body(struct bpf_prog *fp, u32 *image,
|
|||
u64 imm64;
|
||||
u8 *func;
|
||||
u32 true_cond;
|
||||
u32 tmp_idx;
|
||||
|
||||
/*
|
||||
* addrs[] maps a BPF bytecode address into a real offset from
|
||||
|
@ -637,11 +638,7 @@ static int bpf_jit_build_body(struct bpf_prog *fp, u32 *image,
|
|||
case BPF_STX | BPF_XADD | BPF_W:
|
||||
/* Get EA into TMP_REG_1 */
|
||||
PPC_ADDI(b2p[TMP_REG_1], dst_reg, off);
|
||||
/* error if EA is not word-aligned */
|
||||
PPC_ANDI(b2p[TMP_REG_2], b2p[TMP_REG_1], 0x03);
|
||||
PPC_BCC_SHORT(COND_EQ, (ctx->idx * 4) + 12);
|
||||
PPC_LI(b2p[BPF_REG_0], 0);
|
||||
PPC_JMP(exit_addr);
|
||||
tmp_idx = ctx->idx * 4;
|
||||
/* load value from memory into TMP_REG_2 */
|
||||
PPC_BPF_LWARX(b2p[TMP_REG_2], 0, b2p[TMP_REG_1], 0);
|
||||
/* add value from src_reg into this */
|
||||
|
@ -649,32 +646,16 @@ static int bpf_jit_build_body(struct bpf_prog *fp, u32 *image,
|
|||
/* store result back */
|
||||
PPC_BPF_STWCX(b2p[TMP_REG_2], 0, b2p[TMP_REG_1]);
|
||||
/* we're done if this succeeded */
|
||||
PPC_BCC_SHORT(COND_EQ, (ctx->idx * 4) + (7*4));
|
||||
/* otherwise, let's try once more */
|
||||
PPC_BPF_LWARX(b2p[TMP_REG_2], 0, b2p[TMP_REG_1], 0);
|
||||
PPC_ADD(b2p[TMP_REG_2], b2p[TMP_REG_2], src_reg);
|
||||
PPC_BPF_STWCX(b2p[TMP_REG_2], 0, b2p[TMP_REG_1]);
|
||||
/* exit if the store was not successful */
|
||||
PPC_LI(b2p[BPF_REG_0], 0);
|
||||
PPC_BCC(COND_NE, exit_addr);
|
||||
PPC_BCC_SHORT(COND_NE, tmp_idx);
|
||||
break;
|
||||
/* *(u64 *)(dst + off) += src */
|
||||
case BPF_STX | BPF_XADD | BPF_DW:
|
||||
PPC_ADDI(b2p[TMP_REG_1], dst_reg, off);
|
||||
/* error if EA is not doubleword-aligned */
|
||||
PPC_ANDI(b2p[TMP_REG_2], b2p[TMP_REG_1], 0x07);
|
||||
PPC_BCC_SHORT(COND_EQ, (ctx->idx * 4) + (3*4));
|
||||
PPC_LI(b2p[BPF_REG_0], 0);
|
||||
PPC_JMP(exit_addr);
|
||||
tmp_idx = ctx->idx * 4;
|
||||
PPC_BPF_LDARX(b2p[TMP_REG_2], 0, b2p[TMP_REG_1], 0);
|
||||
PPC_ADD(b2p[TMP_REG_2], b2p[TMP_REG_2], src_reg);
|
||||
PPC_BPF_STDCX(b2p[TMP_REG_2], 0, b2p[TMP_REG_1]);
|
||||
PPC_BCC_SHORT(COND_EQ, (ctx->idx * 4) + (7*4));
|
||||
PPC_BPF_LDARX(b2p[TMP_REG_2], 0, b2p[TMP_REG_1], 0);
|
||||
PPC_ADD(b2p[TMP_REG_2], b2p[TMP_REG_2], src_reg);
|
||||
PPC_BPF_STDCX(b2p[TMP_REG_2], 0, b2p[TMP_REG_1]);
|
||||
PPC_LI(b2p[BPF_REG_0], 0);
|
||||
PPC_BCC(COND_NE, exit_addr);
|
||||
PPC_BCC_SHORT(COND_NE, tmp_idx);
|
||||
break;
|
||||
|
||||
/*
|
||||
|
|
Loading…
Reference in a new issue