|
Jiri Slaby |
6b3564 |
From: John Fastabend <john.fastabend@gmail.com>
|
|
Jiri Slaby |
6b3564 |
Date: Sun, 2 Jul 2017 02:13:30 +0200
|
|
Jiri Slaby |
6b3564 |
Subject: [PATCH] bpf, verifier: add additional patterns to
|
|
Jiri Slaby |
6b3564 |
evaluate_reg_imm_alu
|
|
Jiri Slaby |
6b3564 |
References: bnc#1060662
|
|
Thomas Zimmermann |
1d81d2 |
Patch-mainline: v4.12.10
|
|
Jiri Slaby |
6b3564 |
Git-commit: 43188702b3d98d2792969a3377a30957f05695e6
|
|
Jiri Slaby |
6b3564 |
|
|
Jiri Slaby |
6b3564 |
[ Upstream commit 43188702b3d98d2792969a3377a30957f05695e6 ]
|
|
Jiri Slaby |
6b3564 |
|
|
Jiri Slaby |
6b3564 |
Currently the verifier does not track imm across alu operations when
|
|
Jiri Slaby |
6b3564 |
the source register is of unknown type. This adds additional pattern
|
|
Jiri Slaby |
6b3564 |
matching to catch this and track imm. We've seen LLVM generating this
|
|
Jiri Slaby |
6b3564 |
pattern while working on cilium.
|
|
Jiri Slaby |
6b3564 |
|
|
Jiri Slaby |
6b3564 |
Signed-off-by: John Fastabend <john.fastabend@gmail.com>
|
|
Jiri Slaby |
6b3564 |
Acked-by: Daniel Borkmann <daniel@iogearbox.net>
|
|
Jiri Slaby |
6b3564 |
Acked-by: Alexei Starovoitov <ast@kernel.org>
|
|
Jiri Slaby |
6b3564 |
Signed-off-by: David S. Miller <davem@davemloft.net>
|
|
Jiri Slaby |
6b3564 |
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
|
Jiri Slaby |
6b3564 |
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
|
|
Jiri Slaby |
6b3564 |
---
|
|
Jiri Slaby |
6b3564 |
kernel/bpf/verifier.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
Jiri Slaby |
6b3564 |
1 file changed, 62 insertions(+)
|
|
Jiri Slaby |
6b3564 |
|
|
Jiri Slaby |
6b3564 |
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
|
|
Jiri Slaby |
6b3564 |
index a8a725697bed..03f8d02849be 100644
|
|
Jiri Slaby |
6b3564 |
--- a/kernel/bpf/verifier.c
|
|
Jiri Slaby |
6b3564 |
+++ b/kernel/bpf/verifier.c
|
|
Jiri Slaby |
6b3564 |
@@ -1650,6 +1650,65 @@ static int evaluate_reg_alu(struct bpf_verifier_env *env, struct bpf_insn *insn)
|
|
Jiri Slaby |
6b3564 |
return 0;
|
|
Jiri Slaby |
6b3564 |
}
|
|
Jiri Slaby |
6b3564 |
|
|
Jiri Slaby |
6b3564 |
+static int evaluate_reg_imm_alu_unknown(struct bpf_verifier_env *env,
|
|
Jiri Slaby |
6b3564 |
+ struct bpf_insn *insn)
|
|
Jiri Slaby |
6b3564 |
+{
|
|
Jiri Slaby |
6b3564 |
+ struct bpf_reg_state *regs = env->cur_state.regs;
|
|
Jiri Slaby |
6b3564 |
+ struct bpf_reg_state *dst_reg = ®s[insn->dst_reg];
|
|
Jiri Slaby |
6b3564 |
+ struct bpf_reg_state *src_reg = ®s[insn->src_reg];
|
|
Jiri Slaby |
6b3564 |
+ u8 opcode = BPF_OP(insn->code);
|
|
Jiri Slaby |
6b3564 |
+ s64 imm_log2 = __ilog2_u64((long long)dst_reg->imm);
|
|
Jiri Slaby |
6b3564 |
+
|
|
Jiri Slaby |
6b3564 |
+ /* BPF_X code with src_reg->type UNKNOWN_VALUE here. */
|
|
Jiri Slaby |
6b3564 |
+ if (src_reg->imm > 0 && dst_reg->imm) {
|
|
Jiri Slaby |
6b3564 |
+ switch (opcode) {
|
|
Jiri Slaby |
6b3564 |
+ case BPF_ADD:
|
|
Jiri Slaby |
6b3564 |
+ /* dreg += sreg
|
|
Jiri Slaby |
6b3564 |
+ * where both have zero upper bits. Adding them
|
|
Jiri Slaby |
6b3564 |
+ * can only result making one more bit non-zero
|
|
Jiri Slaby |
6b3564 |
+ * in the larger value.
|
|
Jiri Slaby |
6b3564 |
+ * Ex. 0xffff (imm=48) + 1 (imm=63) = 0x10000 (imm=47)
|
|
Jiri Slaby |
6b3564 |
+ * 0xffff (imm=48) + 0xffff = 0x1fffe (imm=47)
|
|
Jiri Slaby |
6b3564 |
+ */
|
|
Jiri Slaby |
6b3564 |
+ dst_reg->imm = min(src_reg->imm, 63 - imm_log2);
|
|
Jiri Slaby |
6b3564 |
+ dst_reg->imm--;
|
|
Jiri Slaby |
6b3564 |
+ break;
|
|
Jiri Slaby |
6b3564 |
+ case BPF_AND:
|
|
Jiri Slaby |
6b3564 |
+ /* dreg &= sreg
|
|
Jiri Slaby |
6b3564 |
+ * AND can not extend zero bits only shrink
|
|
Jiri Slaby |
6b3564 |
+ * Ex. 0x00..00ffffff
|
|
Jiri Slaby |
6b3564 |
+ * & 0x0f..ffffffff
|
|
Jiri Slaby |
6b3564 |
+ * ----------------
|
|
Jiri Slaby |
6b3564 |
+ * 0x00..00ffffff
|
|
Jiri Slaby |
6b3564 |
+ */
|
|
Jiri Slaby |
6b3564 |
+ dst_reg->imm = max(src_reg->imm, 63 - imm_log2);
|
|
Jiri Slaby |
6b3564 |
+ break;
|
|
Jiri Slaby |
6b3564 |
+ case BPF_OR:
|
|
Jiri Slaby |
6b3564 |
+ /* dreg |= sreg
|
|
Jiri Slaby |
6b3564 |
+ * OR can only extend zero bits
|
|
Jiri Slaby |
6b3564 |
+ * Ex. 0x00..00ffffff
|
|
Jiri Slaby |
6b3564 |
+ * | 0x0f..ffffffff
|
|
Jiri Slaby |
6b3564 |
+ * ----------------
|
|
Jiri Slaby |
6b3564 |
+ * 0x0f..00ffffff
|
|
Jiri Slaby |
6b3564 |
+ */
|
|
Jiri Slaby |
6b3564 |
+ dst_reg->imm = min(src_reg->imm, 63 - imm_log2);
|
|
Jiri Slaby |
6b3564 |
+ break;
|
|
Jiri Slaby |
6b3564 |
+ case BPF_SUB:
|
|
Jiri Slaby |
6b3564 |
+ case BPF_MUL:
|
|
Jiri Slaby |
6b3564 |
+ case BPF_RSH:
|
|
Jiri Slaby |
6b3564 |
+ case BPF_LSH:
|
|
Jiri Slaby |
6b3564 |
+ /* These may be flushed out later */
|
|
Jiri Slaby |
6b3564 |
+ default:
|
|
Jiri Slaby |
6b3564 |
+ mark_reg_unknown_value(regs, insn->dst_reg);
|
|
Jiri Slaby |
6b3564 |
+ }
|
|
Jiri Slaby |
6b3564 |
+ } else {
|
|
Jiri Slaby |
6b3564 |
+ mark_reg_unknown_value(regs, insn->dst_reg);
|
|
Jiri Slaby |
6b3564 |
+ }
|
|
Jiri Slaby |
6b3564 |
+
|
|
Jiri Slaby |
6b3564 |
+ dst_reg->type = UNKNOWN_VALUE;
|
|
Jiri Slaby |
6b3564 |
+ return 0;
|
|
Jiri Slaby |
6b3564 |
+}
|
|
Jiri Slaby |
6b3564 |
+
|
|
Jiri Slaby |
6b3564 |
static int evaluate_reg_imm_alu(struct bpf_verifier_env *env,
|
|
Jiri Slaby |
6b3564 |
struct bpf_insn *insn)
|
|
Jiri Slaby |
6b3564 |
{
|
|
Jiri Slaby |
6b3564 |
@@ -1659,6 +1718,9 @@ static int evaluate_reg_imm_alu(struct bpf_verifier_env *env,
|
|
Jiri Slaby |
6b3564 |
u8 opcode = BPF_OP(insn->code);
|
|
Jiri Slaby |
6b3564 |
u64 dst_imm = dst_reg->imm;
|
|
Jiri Slaby |
6b3564 |
|
|
Jiri Slaby |
6b3564 |
+ if (BPF_SRC(insn->code) == BPF_X && src_reg->type == UNKNOWN_VALUE)
|
|
Jiri Slaby |
6b3564 |
+ return evaluate_reg_imm_alu_unknown(env, insn);
|
|
Jiri Slaby |
6b3564 |
+
|
|
Jiri Slaby |
6b3564 |
/* dst_reg->type == CONST_IMM here. Simulate execution of insns
|
|
Jiri Slaby |
6b3564 |
* containing ALU ops. Don't care about overflow or negative
|
|
Jiri Slaby |
6b3564 |
* values, just add/sub/... them; registers are in u64.
|
|
Jiri Slaby |
6b3564 |
--
|
|
Jiri Slaby |
6b3564 |
2.14.2
|
|
Jiri Slaby |
6b3564 |
|