diff options
author | Andreas Wellving <andreas.wellving@enea.com> | 2019-05-21 14:06:19 +0200 |
---|---|---|
committer | Adrian Mangeac <Adrian.Mangeac@enea.com> | 2019-05-21 16:38:10 +0200 |
commit | fab791dcdc422b78816917e207fd2563ab14a3a2 (patch) | |
tree | 5e1a70ff79f7009cc6b8bba45372ce2348e766f8 | |
parent | 095a278de3d367f1a5cf54dfcf4f68d042bcf66b (diff) | |
download | enea-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.patch | 75 |
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 @@ | |||
1 | From 4d54f7df5131d67f653f674003ec5f52c9818b53 Mon Sep 17 00:00:00 2001 | ||
2 | From: Daniel Borkmann <daniel@iogearbox.net> | ||
3 | Date: Fri, 22 Dec 2017 16:23:04 +0100 | ||
4 | Subject: [PATCH] bpf/verifier: fix bounds calculation on BPF_RSH | ||
5 | |||
6 | From: Edward Cree <ecree@solarflare.com> | ||
7 | |||
8 | [ Upstream commit 4374f256ce8182019353c0c639bb8d0695b4c941 ] | ||
9 | |||
10 | Incorrect signed bounds were being computed. | ||
11 | If the old upper signed bound was positive and the old lower signed bound was | ||
12 | negative, this could cause the new upper signed bound to be too low, | ||
13 | leading to security issues. | ||
14 | |||
15 | CVE: CVE-2017-17853 | ||
16 | Upstream-Status: Backport [https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?h=linux-4.14.y&id=4d54f7df5131d67f653f674003ec5f52c9818b53] | ||
17 | |||
18 | Fixes: b03c9f9fdc37 ("bpf/verifier: track signed and unsigned min/max values") | ||
19 | Reported-by: Jann Horn <jannh@google.com> | ||
20 | Signed-off-by: Edward Cree <ecree@solarflare.com> | ||
21 | Acked-by: Alexei Starovoitov <ast@kernel.org> | ||
22 | [jannh@google.com: changed description to reflect bug impact] | ||
23 | Signed-off-by: Jann Horn <jannh@google.com> | ||
24 | Signed-off-by: Alexei Starovoitov <ast@kernel.org> | ||
25 | Signed-off-by: Daniel Borkmann <daniel@iogearbox.net> | ||
26 | Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> | ||
27 | Signed-off-by: Andreas Wellving <andreas.wellving@enea.com> | ||
28 | --- | ||
29 | kernel/bpf/verifier.c | 30 ++++++++++++++++-------------- | ||
30 | 1 file changed, 16 insertions(+), 14 deletions(-) | ||
31 | |||
32 | diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c | ||
33 | index 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 | -- | ||
74 | 2.20.1 | ||
75 | |||