mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-26 21:54:11 +08:00
bpf, mips64: remove unneeded zero check from div/mod with k
The verifier in both cBPF and eBPF reject div/mod by 0 imm, so this can never load. Remove emitting such test and reject it from being JITed instead (the latter is actually also not needed, but given practice in sparc64, ppc64 today, so doesn't hurt to add it here either). Signed-off-by: Daniel Borkmann <daniel@iogearbox.net> Cc: David Daney <david.daney@cavium.com> Reviewed-by: David Daney <david.daney@cavium.com> Signed-off-by: Alexei Starovoitov <ast@kernel.org>
This commit is contained in:
parent
1fb5c9c622
commit
e472d5d8af
@ -741,16 +741,11 @@ static int build_one_insn(const struct bpf_insn *insn, struct jit_ctx *ctx,
|
|||||||
break;
|
break;
|
||||||
case BPF_ALU | BPF_DIV | BPF_K: /* ALU_IMM */
|
case BPF_ALU | BPF_DIV | BPF_K: /* ALU_IMM */
|
||||||
case BPF_ALU | BPF_MOD | BPF_K: /* ALU_IMM */
|
case BPF_ALU | BPF_MOD | BPF_K: /* ALU_IMM */
|
||||||
|
if (insn->imm == 0)
|
||||||
|
return -EINVAL;
|
||||||
dst = ebpf_to_mips_reg(ctx, insn, dst_reg);
|
dst = ebpf_to_mips_reg(ctx, insn, dst_reg);
|
||||||
if (dst < 0)
|
if (dst < 0)
|
||||||
return dst;
|
return dst;
|
||||||
if (insn->imm == 0) { /* Div by zero */
|
|
||||||
b_off = b_imm(exit_idx, ctx);
|
|
||||||
if (is_bad_offset(b_off))
|
|
||||||
return -E2BIG;
|
|
||||||
emit_instr(ctx, beq, MIPS_R_ZERO, MIPS_R_ZERO, b_off);
|
|
||||||
emit_instr(ctx, addu, MIPS_R_V0, MIPS_R_ZERO, MIPS_R_ZERO);
|
|
||||||
}
|
|
||||||
td = get_reg_val_type(ctx, this_idx, insn->dst_reg);
|
td = get_reg_val_type(ctx, this_idx, insn->dst_reg);
|
||||||
if (td == REG_64BIT || td == REG_32BIT_ZERO_EX)
|
if (td == REG_64BIT || td == REG_32BIT_ZERO_EX)
|
||||||
/* sign extend */
|
/* sign extend */
|
||||||
@ -770,19 +765,13 @@ static int build_one_insn(const struct bpf_insn *insn, struct jit_ctx *ctx,
|
|||||||
break;
|
break;
|
||||||
case BPF_ALU64 | BPF_DIV | BPF_K: /* ALU_IMM */
|
case BPF_ALU64 | BPF_DIV | BPF_K: /* ALU_IMM */
|
||||||
case BPF_ALU64 | BPF_MOD | BPF_K: /* ALU_IMM */
|
case BPF_ALU64 | BPF_MOD | BPF_K: /* ALU_IMM */
|
||||||
|
if (insn->imm == 0)
|
||||||
|
return -EINVAL;
|
||||||
dst = ebpf_to_mips_reg(ctx, insn, dst_reg);
|
dst = ebpf_to_mips_reg(ctx, insn, dst_reg);
|
||||||
if (dst < 0)
|
if (dst < 0)
|
||||||
return dst;
|
return dst;
|
||||||
if (insn->imm == 0) { /* Div by zero */
|
|
||||||
b_off = b_imm(exit_idx, ctx);
|
|
||||||
if (is_bad_offset(b_off))
|
|
||||||
return -E2BIG;
|
|
||||||
emit_instr(ctx, beq, MIPS_R_ZERO, MIPS_R_ZERO, b_off);
|
|
||||||
emit_instr(ctx, addu, MIPS_R_V0, MIPS_R_ZERO, MIPS_R_ZERO);
|
|
||||||
}
|
|
||||||
if (get_reg_val_type(ctx, this_idx, insn->dst_reg) == REG_32BIT)
|
if (get_reg_val_type(ctx, this_idx, insn->dst_reg) == REG_32BIT)
|
||||||
emit_instr(ctx, dinsu, dst, MIPS_R_ZERO, 32, 32);
|
emit_instr(ctx, dinsu, dst, MIPS_R_ZERO, 32, 32);
|
||||||
|
|
||||||
if (insn->imm == 1) {
|
if (insn->imm == 1) {
|
||||||
/* div by 1 is a nop, mod by 1 is zero */
|
/* div by 1 is a nop, mod by 1 is zero */
|
||||||
if (bpf_op == BPF_MOD)
|
if (bpf_op == BPF_MOD)
|
||||||
|
Loading…
Reference in New Issue
Block a user