summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndreas Wellving <andreas.wellving@enea.com>2019-05-21 14:16:44 +0200
committerAdrian Mangeac <Adrian.Mangeac@enea.com>2019-05-21 16:39:53 +0200
commit2d046ce88b7f6bab96f40856e3d450a6daa7364c (patch)
tree9c77322d138b45fb53bac54f91e31ad470a6e475
parentfab791dcdc422b78816917e207fd2563ab14a3a2 (diff)
downloadenea-kernel-cache-2d046ce88b7f6bab96f40856e3d450a6daa7364c.tar.gz
bpf: CVE-2017-17854
bpf: fix integer overflows Reference: https://nvd.nist.gov/vuln/detail/CVE-2017-17854 https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?h=linux-4.14.y&id=de31796c052e47c99b1bb342bc70aa826733e862 Change-Id: I00c2d0e05420994cd67f689f0ad63f0a0fbde2e9 Signed-off-by: Andreas Wellving <andreas.wellving@enea.com>
-rw-r--r--patches/cve/CVE-2017-17854-bpf-fix-integer-overflows.patch137
1 files changed, 137 insertions, 0 deletions
diff --git a/patches/cve/CVE-2017-17854-bpf-fix-integer-overflows.patch b/patches/cve/CVE-2017-17854-bpf-fix-integer-overflows.patch
new file mode 100644
index 0000000..3ac7eca
--- /dev/null
+++ b/patches/cve/CVE-2017-17854-bpf-fix-integer-overflows.patch
@@ -0,0 +1,137 @@
1From de31796c052e47c99b1bb342bc70aa826733e862 Mon Sep 17 00:00:00 2001
2From: Daniel Borkmann <daniel@iogearbox.net>
3Date: Fri, 22 Dec 2017 16:23:11 +0100
4Subject: [PATCH] bpf: fix integer overflows
5
6From: Alexei Starovoitov <ast@kernel.org>
7
8[ Upstream commit bb7f0f989ca7de1153bd128a40a71709e339fa03 ]
9
10There were various issues related to the limited size of integers used in
11the verifier:
12 - `off + size` overflow in __check_map_access()
13 - `off + reg->off` overflow in check_mem_access()
14 - `off + reg->var_off.value` overflow or 32-bit truncation of
15 `reg->var_off.value` in check_mem_access()
16 - 32-bit truncation in check_stack_boundary()
17
18Make sure that any integer math cannot overflow by not allowing
19pointer math with large values.
20
21Also reduce the scope of "scalar op scalar" tracking.
22
23CVE: CVE-2017-17854
24Upstream-Status: Backport [https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?h=linux-4.14.y&id=de31796c052e47c99b1bb342bc70aa826733e862]
25
26Fixes: f1174f77b50c ("bpf/verifier: rework value tracking")
27Reported-by: Jann Horn <jannh@google.com>
28Signed-off-by: Alexei Starovoitov <ast@kernel.org>
29Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
30Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
31Signed-off-by: Andreas Wellving <andreas.wellving@enea.com>
32---
33 include/linux/bpf_verifier.h | 4 +--
34 kernel/bpf/verifier.c | 48 ++++++++++++++++++++++++++++++++++++
35 2 files changed, 50 insertions(+), 2 deletions(-)
36
37diff --git a/include/linux/bpf_verifier.h b/include/linux/bpf_verifier.h
38index 5d6de3b57758..73bec75b74c8 100644
39--- a/include/linux/bpf_verifier.h
40+++ b/include/linux/bpf_verifier.h
41@@ -15,11 +15,11 @@
42 * In practice this is far bigger than any realistic pointer offset; this limit
43 * ensures that umax_value + (int)off + (int)size cannot overflow a u64.
44 */
45-#define BPF_MAX_VAR_OFF (1ULL << 31)
46+#define BPF_MAX_VAR_OFF (1 << 29)
47 /* Maximum variable size permitted for ARG_CONST_SIZE[_OR_ZERO]. This ensures
48 * that converting umax_value to int cannot overflow.
49 */
50-#define BPF_MAX_VAR_SIZ INT_MAX
51+#define BPF_MAX_VAR_SIZ (1 << 29)
52
53 /* Liveness marks, used for registers and spilled-regs (in stack slots).
54 * Read marks propagate upwards until they find a write mark; they record that
55diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
56index 5a30eda17c4f..c5ff809e86d0 100644
57--- a/kernel/bpf/verifier.c
58+++ b/kernel/bpf/verifier.c
59@@ -1789,6 +1789,41 @@ static bool signed_sub_overflows(s64 a, s64 b)
60 return res > a;
61 }
62
63+static bool check_reg_sane_offset(struct bpf_verifier_env *env,
64+ const struct bpf_reg_state *reg,
65+ enum bpf_reg_type type)
66+{
67+ bool known = tnum_is_const(reg->var_off);
68+ s64 val = reg->var_off.value;
69+ s64 smin = reg->smin_value;
70+
71+ if (known && (val >= BPF_MAX_VAR_OFF || val <= -BPF_MAX_VAR_OFF)) {
72+ verbose("math between %s pointer and %lld is not allowed\n",
73+ reg_type_str[type], val);
74+ return false;
75+ }
76+
77+ if (reg->off >= BPF_MAX_VAR_OFF || reg->off <= -BPF_MAX_VAR_OFF) {
78+ verbose("%s pointer offset %d is not allowed\n",
79+ reg_type_str[type], reg->off);
80+ return false;
81+ }
82+
83+ if (smin == S64_MIN) {
84+ verbose("math between %s pointer and register with unbounded min value is not allowed\n",
85+ reg_type_str[type]);
86+ return false;
87+ }
88+
89+ if (smin >= BPF_MAX_VAR_OFF || smin <= -BPF_MAX_VAR_OFF) {
90+ verbose("value %lld makes %s pointer be out of bounds\n",
91+ smin, reg_type_str[type]);
92+ return false;
93+ }
94+
95+ return true;
96+}
97+
98 /* Handles arithmetic on a pointer and a scalar: computes new min/max and var_off.
99 * Caller should also handle BPF_MOV case separately.
100 * If we return -EACCES, caller may want to try again treating pointer as a
101@@ -1854,6 +1889,10 @@ static int adjust_ptr_min_max_vals(struct bpf_verifier_env *env,
102 dst_reg->type = ptr_reg->type;
103 dst_reg->id = ptr_reg->id;
104
105+ if (!check_reg_sane_offset(env, off_reg, ptr_reg->type) ||
106+ !check_reg_sane_offset(env, ptr_reg, ptr_reg->type))
107+ return -EINVAL;
108+
109 switch (opcode) {
110 case BPF_ADD:
111 /* We can take a fixed offset as long as it doesn't overflow
112@@ -1984,6 +2023,9 @@ static int adjust_ptr_min_max_vals(struct bpf_verifier_env *env,
113 return -EACCES;
114 }
115
116+ if (!check_reg_sane_offset(env, dst_reg, ptr_reg->type))
117+ return -EINVAL;
118+
119 __update_reg_bounds(dst_reg);
120 __reg_deduce_bounds(dst_reg);
121 __reg_bound_offset(dst_reg);
122@@ -2013,6 +2055,12 @@ static int adjust_scalar_min_max_vals(struct bpf_verifier_env *env,
123 src_known = tnum_is_const(src_reg.var_off);
124 dst_known = tnum_is_const(dst_reg->var_off);
125
126+ if (!src_known &&
127+ opcode != BPF_ADD && opcode != BPF_SUB && opcode != BPF_AND) {
128+ __mark_reg_unknown(dst_reg);
129+ return 0;
130+ }
131+
132 switch (opcode) {
133 case BPF_ADD:
134 if (signed_add_overflows(dst_reg->smin_value, smin_val) ||
135--
1362.20.1
137