summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndreas Wellving <andreas.wellving@enea.com>2019-05-21 14:06:19 +0200
committerAdrian Mangeac <Adrian.Mangeac@enea.com>2019-05-21 16:38:10 +0200
commitfab791dcdc422b78816917e207fd2563ab14a3a2 (patch)
tree5e1a70ff79f7009cc6b8bba45372ce2348e766f8
parent095a278de3d367f1a5cf54dfcf4f68d042bcf66b (diff)
downloadenea-kernel-cache-fab791dcdc422b78816917e207fd2563ab14a3a2.tar.gz
bpf/verifier: CVE-2017-17853
bpf/verifier: fix bounds calculation on BPF_RSH Reference: https://nvd.nist.gov/vuln/detail/CVE-2017-17853 https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?h=linux-4.14.y&id=4d54f7df5131d67f653f674003ec5f52c9818b53 Change-Id: I05c37ee9076a249d1a58ec631b22518e3558759e Signed-off-by: Andreas Wellving <andreas.wellving@enea.com>
-rw-r--r--patches/cve/CVE-2017-17853-bpf-verifier-fix-bounds-calculation-on-BPF_RSH.patch75
1 files changed, 75 insertions, 0 deletions
diff --git a/patches/cve/CVE-2017-17853-bpf-verifier-fix-bounds-calculation-on-BPF_RSH.patch b/patches/cve/CVE-2017-17853-bpf-verifier-fix-bounds-calculation-on-BPF_RSH.patch
new file mode 100644
index 0000000..eecef57
--- /dev/null
+++ b/patches/cve/CVE-2017-17853-bpf-verifier-fix-bounds-calculation-on-BPF_RSH.patch
@@ -0,0 +1,75 @@
1From 4d54f7df5131d67f653f674003ec5f52c9818b53 Mon Sep 17 00:00:00 2001
2From: Daniel Borkmann <daniel@iogearbox.net>
3Date: Fri, 22 Dec 2017 16:23:04 +0100
4Subject: [PATCH] bpf/verifier: fix bounds calculation on BPF_RSH
5
6From: Edward Cree <ecree@solarflare.com>
7
8[ Upstream commit 4374f256ce8182019353c0c639bb8d0695b4c941 ]
9
10Incorrect signed bounds were being computed.
11If the old upper signed bound was positive and the old lower signed bound was
12negative, this could cause the new upper signed bound to be too low,
13leading to security issues.
14
15CVE: CVE-2017-17853
16Upstream-Status: Backport [https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?h=linux-4.14.y&id=4d54f7df5131d67f653f674003ec5f52c9818b53]
17
18Fixes: b03c9f9fdc37 ("bpf/verifier: track signed and unsigned min/max values")
19Reported-by: Jann Horn <jannh@google.com>
20Signed-off-by: Edward Cree <ecree@solarflare.com>
21Acked-by: Alexei Starovoitov <ast@kernel.org>
22[jannh@google.com: changed description to reflect bug impact]
23Signed-off-by: Jann Horn <jannh@google.com>
24Signed-off-by: Alexei Starovoitov <ast@kernel.org>
25Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
26Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
27Signed-off-by: Andreas Wellving <andreas.wellving@enea.com>
28---
29 kernel/bpf/verifier.c | 30 ++++++++++++++++--------------
30 1 file changed, 16 insertions(+), 14 deletions(-)
31
32diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
33index 201d6b965811..c6ec04f94525 100644
34--- a/kernel/bpf/verifier.c
35+++ b/kernel/bpf/verifier.c
36@@ -2157,20 +2157,22 @@ static int adjust_scalar_min_max_vals(struct bpf_verifier_env *env,
37 mark_reg_unknown(regs, insn->dst_reg);
38 break;
39 }
40- /* BPF_RSH is an unsigned shift, so make the appropriate casts */
41- if (dst_reg->smin_value < 0) {
42- if (umin_val) {
43- /* Sign bit will be cleared */
44- dst_reg->smin_value = 0;
45- } else {
46- /* Lost sign bit information */
47- dst_reg->smin_value = S64_MIN;
48- dst_reg->smax_value = S64_MAX;
49- }
50- } else {
51- dst_reg->smin_value =
52- (u64)(dst_reg->smin_value) >> umax_val;
53- }
54+ /* BPF_RSH is an unsigned shift. If the value in dst_reg might
55+ * be negative, then either:
56+ * 1) src_reg might be zero, so the sign bit of the result is
57+ * unknown, so we lose our signed bounds
58+ * 2) it's known negative, thus the unsigned bounds capture the
59+ * signed bounds
60+ * 3) the signed bounds cross zero, so they tell us nothing
61+ * about the result
62+ * If the value in dst_reg is known nonnegative, then again the
63+ * unsigned bounts capture the signed bounds.
64+ * Thus, in all cases it suffices to blow away our signed bounds
65+ * and rely on inferring new ones from the unsigned bounds and
66+ * var_off of the result.
67+ */
68+ dst_reg->smin_value = S64_MIN;
69+ dst_reg->smax_value = S64_MAX;
70 if (src_known)
71 dst_reg->var_off = tnum_rshift(dst_reg->var_off,
72 umin_val);
73--
742.20.1
75