aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRabin Vincent <rabin@rab.in>2016-01-12 14:17:08 -0500
committerDavid S. Miller <davem@davemloft.net>2016-01-12 15:55:39 -0500
commit06928b3870d213cb42b00e2949419f2d44b9d45f (patch)
treed1427c587b190b02f7d2e5b842c1804f38386128
parent03d84a5f83a67e692af00a3d3901e7820e3e84d5 (diff)
net: bpf: reject invalid shifts
On ARM64, a BUG() is triggered in the eBPF JIT if a filter with a constant shift that can't be encoded in the immediate field of the UBFM/SBFM instructions is passed to the JIT. Since these shifts amounts, which are negative or >= regsize, are invalid, reject them in the eBPF verifier and the classic BPF filter checker, for all architectures. Signed-off-by: Rabin Vincent <rabin@rab.in> Acked-by: Alexei Starovoitov <ast@kernel.org> Acked-by: Daniel Borkmann <daniel@iogearbox.net> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--kernel/bpf/verifier.c10
-rw-r--r--net/core/filter.c5
2 files changed, 15 insertions, 0 deletions
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index a7945d10b378..d1d3e8f57de9 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -1121,6 +1121,16 @@ static int check_alu_op(struct verifier_env *env, struct bpf_insn *insn)
1121 return -EINVAL; 1121 return -EINVAL;
1122 } 1122 }
1123 1123
1124 if ((opcode == BPF_LSH || opcode == BPF_RSH ||
1125 opcode == BPF_ARSH) && BPF_SRC(insn->code) == BPF_K) {
1126 int size = BPF_CLASS(insn->code) == BPF_ALU64 ? 64 : 32;
1127
1128 if (insn->imm < 0 || insn->imm >= size) {
1129 verbose("invalid shift %d\n", insn->imm);
1130 return -EINVAL;
1131 }
1132 }
1133
1124 /* pattern match 'bpf_add Rx, imm' instruction */ 1134 /* pattern match 'bpf_add Rx, imm' instruction */
1125 if (opcode == BPF_ADD && BPF_CLASS(insn->code) == BPF_ALU64 && 1135 if (opcode == BPF_ADD && BPF_CLASS(insn->code) == BPF_ALU64 &&
1126 regs[insn->dst_reg].type == FRAME_PTR && 1136 regs[insn->dst_reg].type == FRAME_PTR &&
diff --git a/net/core/filter.c b/net/core/filter.c
index 672eefbfbe99..37157c4c1a78 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -777,6 +777,11 @@ static int bpf_check_classic(const struct sock_filter *filter,
777 if (ftest->k == 0) 777 if (ftest->k == 0)
778 return -EINVAL; 778 return -EINVAL;
779 break; 779 break;
780 case BPF_ALU | BPF_LSH | BPF_K:
781 case BPF_ALU | BPF_RSH | BPF_K:
782 if (ftest->k >= 32)
783 return -EINVAL;
784 break;
780 case BPF_LD | BPF_MEM: 785 case BPF_LD | BPF_MEM:
781 case BPF_LDX | BPF_MEM: 786 case BPF_LDX | BPF_MEM:
782 case BPF_ST: 787 case BPF_ST: