1 |
From 117630c6b834844132757e90be051611302c5e61 Mon Sep 17 00:00:00 2001 |
2 |
From: Alexei Starovoitov <ast@kernel.org> |
3 |
Date: Tue, 4 Sep 2018 19:13:44 -0700 |
4 |
Subject: [PATCH 063/145] bpf/verifier: fix verifier instability |
5 |
|
6 |
[ Upstream commit a9c676bc8fc58d00eea9836fb14ee43c0346416a ] |
7 |
|
8 |
Edward Cree says: |
9 |
In check_mem_access(), for the PTR_TO_CTX case, after check_ctx_access() |
10 |
has supplied a reg_type, the other members of the register state are set |
11 |
appropriately. Previously reg.range was set to 0, but as it is in a |
12 |
union with reg.map_ptr, which is larger, upper bytes of the latter were |
13 |
left in place. This then caused the memcmp() in regsafe() to fail, |
14 |
preventing some branches from being pruned (and occasionally causing the |
15 |
same program to take a varying number of processed insns on repeated |
16 |
verifier runs). |
17 |
|
18 |
Fix the instability by clearing bpf_reg_state in __mark_reg_[un]known() |
19 |
|
20 |
Fixes: f1174f77b50c ("bpf/verifier: rework value tracking") |
21 |
Debugged-by: Edward Cree <ecree@solarflare.com> |
22 |
Acked-by: Edward Cree <ecree@solarflare.com> |
23 |
Signed-off-by: Alexei Starovoitov <ast@kernel.org> |
24 |
Signed-off-by: Sasha Levin <sashal@kernel.org> |
25 |
--- |
26 |
kernel/bpf/verifier.c | 16 ++++++++-------- |
27 |
1 file changed, 8 insertions(+), 8 deletions(-) |
28 |
|
29 |
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c |
30 |
index 465952a8e465..f0a2f49ff194 100644 |
31 |
--- a/kernel/bpf/verifier.c |
32 |
+++ b/kernel/bpf/verifier.c |
33 |
@@ -553,7 +553,9 @@ static void __mark_reg_not_init(struct bpf_reg_state *reg); |
34 |
*/ |
35 |
static void __mark_reg_known(struct bpf_reg_state *reg, u64 imm) |
36 |
{ |
37 |
- reg->id = 0; |
38 |
+ /* Clear id, off, and union(map_ptr, range) */ |
39 |
+ memset(((u8 *)reg) + sizeof(reg->type), 0, |
40 |
+ offsetof(struct bpf_reg_state, var_off) - sizeof(reg->type)); |
41 |
reg->var_off = tnum_const(imm); |
42 |
reg->smin_value = (s64)imm; |
43 |
reg->smax_value = (s64)imm; |
44 |
@@ -572,7 +574,6 @@ static void __mark_reg_known_zero(struct bpf_reg_state *reg) |
45 |
static void __mark_reg_const_zero(struct bpf_reg_state *reg) |
46 |
{ |
47 |
__mark_reg_known(reg, 0); |
48 |
- reg->off = 0; |
49 |
reg->type = SCALAR_VALUE; |
50 |
} |
51 |
|
52 |
@@ -683,9 +684,12 @@ static void __mark_reg_unbounded(struct bpf_reg_state *reg) |
53 |
/* Mark a register as having a completely unknown (scalar) value. */ |
54 |
static void __mark_reg_unknown(struct bpf_reg_state *reg) |
55 |
{ |
56 |
+ /* |
57 |
+ * Clear type, id, off, and union(map_ptr, range) and |
58 |
+ * padding between 'type' and union |
59 |
+ */ |
60 |
+ memset(reg, 0, offsetof(struct bpf_reg_state, var_off)); |
61 |
reg->type = SCALAR_VALUE; |
62 |
- reg->id = 0; |
63 |
- reg->off = 0; |
64 |
reg->var_off = tnum_unknown; |
65 |
reg->frameno = 0; |
66 |
__mark_reg_unbounded(reg); |
67 |
@@ -1727,9 +1731,6 @@ static int check_mem_access(struct bpf_verifier_env *env, int insn_idx, u32 regn |
68 |
else |
69 |
mark_reg_known_zero(env, regs, |
70 |
value_regno); |
71 |
- regs[value_regno].id = 0; |
72 |
- regs[value_regno].off = 0; |
73 |
- regs[value_regno].range = 0; |
74 |
regs[value_regno].type = reg_type; |
75 |
} |
76 |
|
77 |
@@ -2580,7 +2581,6 @@ static int check_helper_call(struct bpf_verifier_env *env, int func_id, int insn |
78 |
regs[BPF_REG_0].type = PTR_TO_MAP_VALUE_OR_NULL; |
79 |
/* There is no offset yet applied, variable or fixed */ |
80 |
mark_reg_known_zero(env, regs, BPF_REG_0); |
81 |
- regs[BPF_REG_0].off = 0; |
82 |
/* remember map_ptr, so that check_map_access() |
83 |
* can check 'value_size' boundary of memory access |
84 |
* to map element returned from bpf_map_lookup_elem() |
85 |
-- |
86 |
2.19.1 |
87 |
|