aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Borkmann <daniel@iogearbox.net>2018-01-26 17:33:46 -0500
committerAlexei Starovoitov <ast@kernel.org>2018-01-26 19:42:06 -0500
commite472d5d8afeccca835334d10e0f9389d2baba9c0 (patch)
treec05f720f1550220c52e6e4716118dfb18e19d701
parent1fb5c9c622c559e1524a419358c78397be822dda (diff)
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>
-rw-r--r--arch/mips/net/ebpf_jit.c19
1 files changed, 4 insertions, 15 deletions
diff --git a/arch/mips/net/ebpf_jit.c b/arch/mips/net/ebpf_jit.c
index 296f1410ae5c..3e2798bfea4f 100644
--- a/arch/mips/net/ebpf_jit.c
+++ b/arch/mips/net/ebpf_jit.c
@@ -741,16 +741,11 @@ static int build_one_insn(const struct bpf_insn *insn, struct jit_ctx *ctx,
741 break; 741 break;
742 case BPF_ALU | BPF_DIV | BPF_K: /* ALU_IMM */ 742 case BPF_ALU | BPF_DIV | BPF_K: /* ALU_IMM */
743 case BPF_ALU | BPF_MOD | BPF_K: /* ALU_IMM */ 743 case BPF_ALU | BPF_MOD | BPF_K: /* ALU_IMM */
744 if (insn->imm == 0)
745 return -EINVAL;
744 dst = ebpf_to_mips_reg(ctx, insn, dst_reg); 746 dst = ebpf_to_mips_reg(ctx, insn, dst_reg);
745 if (dst < 0) 747 if (dst < 0)
746 return dst; 748 return dst;
747 if (insn->imm == 0) { /* Div by zero */
748 b_off = b_imm(exit_idx, ctx);
749 if (is_bad_offset(b_off))
750 return -E2BIG;
751 emit_instr(ctx, beq, MIPS_R_ZERO, MIPS_R_ZERO, b_off);
752 emit_instr(ctx, addu, MIPS_R_V0, MIPS_R_ZERO, MIPS_R_ZERO);
753 }
754 td = get_reg_val_type(ctx, this_idx, insn->dst_reg); 749 td = get_reg_val_type(ctx, this_idx, insn->dst_reg);
755 if (td == REG_64BIT || td == REG_32BIT_ZERO_EX) 750 if (td == REG_64BIT || td == REG_32BIT_ZERO_EX)
756 /* sign extend */ 751 /* sign extend */
@@ -770,19 +765,13 @@ static int build_one_insn(const struct bpf_insn *insn, struct jit_ctx *ctx,
770 break; 765 break;
771 case BPF_ALU64 | BPF_DIV | BPF_K: /* ALU_IMM */ 766 case BPF_ALU64 | BPF_DIV | BPF_K: /* ALU_IMM */
772 case BPF_ALU64 | BPF_MOD | BPF_K: /* ALU_IMM */ 767 case BPF_ALU64 | BPF_MOD | BPF_K: /* ALU_IMM */
768 if (insn->imm == 0)
769 return -EINVAL;
773 dst = ebpf_to_mips_reg(ctx, insn, dst_reg); 770 dst = ebpf_to_mips_reg(ctx, insn, dst_reg);
774 if (dst < 0) 771 if (dst < 0)
775 return dst; 772 return dst;
776 if (insn->imm == 0) { /* Div by zero */
777 b_off = b_imm(exit_idx, ctx);
778 if (is_bad_offset(b_off))
779 return -E2BIG;
780 emit_instr(ctx, beq, MIPS_R_ZERO, MIPS_R_ZERO, b_off);
781 emit_instr(ctx, addu, MIPS_R_V0, MIPS_R_ZERO, MIPS_R_ZERO);
782 }
783 if (get_reg_val_type(ctx, this_idx, insn->dst_reg) == REG_32BIT) 773 if (get_reg_val_type(ctx, this_idx, insn->dst_reg) == REG_32BIT)
784 emit_instr(ctx, dinsu, dst, MIPS_R_ZERO, 32, 32); 774 emit_instr(ctx, dinsu, dst, MIPS_R_ZERO, 32, 32);
785
786 if (insn->imm == 1) { 775 if (insn->imm == 1) {
787 /* div by 1 is a nop, mod by 1 is zero */ 776 /* div by 1 is a nop, mod by 1 is zero */
788 if (bpf_op == BPF_MOD) 777 if (bpf_op == BPF_MOD)