diff options
-rw-r--r-- | patches/cve/CVE-2017-17852-bpf-fix-32-bit-ALU-op-verification.patch | 96 |
1 files changed, 96 insertions, 0 deletions
diff --git a/patches/cve/CVE-2017-17852-bpf-fix-32-bit-ALU-op-verification.patch b/patches/cve/CVE-2017-17852-bpf-fix-32-bit-ALU-op-verification.patch new file mode 100644 index 0000000..000e5cd --- /dev/null +++ b/patches/cve/CVE-2017-17852-bpf-fix-32-bit-ALU-op-verification.patch | |||
@@ -0,0 +1,96 @@ | |||
1 | From 6c8e098d0324412d4ae9e06c7e611a96b87faf80 Mon Sep 17 00:00:00 2001 | ||
2 | From: Daniel Borkmann <daniel@iogearbox.net> | ||
3 | Date: Fri, 22 Dec 2017 16:23:07 +0100 | ||
4 | Subject: [PATCH] bpf: fix 32-bit ALU op verification | ||
5 | |||
6 | From: Jann Horn <jannh@google.com> | ||
7 | |||
8 | [ Upstream commit 468f6eafa6c44cb2c5d8aad35e12f06c240a812a ] | ||
9 | |||
10 | 32-bit ALU ops operate on 32-bit values and have 32-bit outputs. | ||
11 | Adjust the verifier accordingly. | ||
12 | |||
13 | CVE: CVE-2017-17852 | ||
14 | Upstream-Status: Backport [https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?h=linux-4.14.y&id=6c8e098d0324412d4ae9e06c7e611a96b87faf80] | ||
15 | |||
16 | Fixes: f1174f77b50c ("bpf/verifier: rework value tracking") | ||
17 | Signed-off-by: Jann Horn <jannh@google.com> | ||
18 | Signed-off-by: Alexei Starovoitov <ast@kernel.org> | ||
19 | Signed-off-by: Daniel Borkmann <daniel@iogearbox.net> | ||
20 | Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> | ||
21 | Signed-off-by: Andreas Wellving <andreas.wellving@enea.com> | ||
22 | --- | ||
23 | kernel/bpf/verifier.c | 28 +++++++++++++++++----------- | ||
24 | 1 file changed, 17 insertions(+), 11 deletions(-) | ||
25 | |||
26 | diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c | ||
27 | index 1e2afb264c31..0c7e4c8a2b8a 100644 | ||
28 | --- a/kernel/bpf/verifier.c | ||
29 | +++ b/kernel/bpf/verifier.c | ||
30 | @@ -1984,6 +1984,10 @@ static int adjust_ptr_min_max_vals(struct bpf_verifier_env *env, | ||
31 | return 0; | ||
32 | } | ||
33 | |||
34 | +/* WARNING: This function does calculations on 64-bit values, but the actual | ||
35 | + * execution may occur on 32-bit values. Therefore, things like bitshifts | ||
36 | + * need extra checks in the 32-bit case. | ||
37 | + */ | ||
38 | static int adjust_scalar_min_max_vals(struct bpf_verifier_env *env, | ||
39 | struct bpf_insn *insn, | ||
40 | struct bpf_reg_state *dst_reg, | ||
41 | @@ -1994,12 +1998,8 @@ static int adjust_scalar_min_max_vals(struct bpf_verifier_env *env, | ||
42 | bool src_known, dst_known; | ||
43 | s64 smin_val, smax_val; | ||
44 | u64 umin_val, umax_val; | ||
45 | + u64 insn_bitness = (BPF_CLASS(insn->code) == BPF_ALU64) ? 64 : 32; | ||
46 | |||
47 | - if (BPF_CLASS(insn->code) != BPF_ALU64) { | ||
48 | - /* 32-bit ALU ops are (32,32)->64 */ | ||
49 | - coerce_reg_to_size(dst_reg, 4); | ||
50 | - coerce_reg_to_size(&src_reg, 4); | ||
51 | - } | ||
52 | smin_val = src_reg.smin_value; | ||
53 | smax_val = src_reg.smax_value; | ||
54 | umin_val = src_reg.umin_value; | ||
55 | @@ -2135,9 +2135,9 @@ static int adjust_scalar_min_max_vals(struct bpf_verifier_env *env, | ||
56 | __update_reg_bounds(dst_reg); | ||
57 | break; | ||
58 | case BPF_LSH: | ||
59 | - if (umax_val > 63) { | ||
60 | - /* Shifts greater than 63 are undefined. This includes | ||
61 | - * shifts by a negative number. | ||
62 | + if (umax_val >= insn_bitness) { | ||
63 | + /* Shifts greater than 31 or 63 are undefined. | ||
64 | + * This includes shifts by a negative number. | ||
65 | */ | ||
66 | mark_reg_unknown(regs, insn->dst_reg); | ||
67 | break; | ||
68 | @@ -2163,9 +2163,9 @@ static int adjust_scalar_min_max_vals(struct bpf_verifier_env *env, | ||
69 | __update_reg_bounds(dst_reg); | ||
70 | break; | ||
71 | case BPF_RSH: | ||
72 | - if (umax_val > 63) { | ||
73 | - /* Shifts greater than 63 are undefined. This includes | ||
74 | - * shifts by a negative number. | ||
75 | + if (umax_val >= insn_bitness) { | ||
76 | + /* Shifts greater than 31 or 63 are undefined. | ||
77 | + * This includes shifts by a negative number. | ||
78 | */ | ||
79 | mark_reg_unknown(regs, insn->dst_reg); | ||
80 | break; | ||
81 | @@ -2201,6 +2201,12 @@ static int adjust_scalar_min_max_vals(struct bpf_verifier_env *env, | ||
82 | break; | ||
83 | } | ||
84 | |||
85 | + if (BPF_CLASS(insn->code) != BPF_ALU64) { | ||
86 | + /* 32-bit ALU ops are (32,32)->32 */ | ||
87 | + coerce_reg_to_size(dst_reg, 4); | ||
88 | + coerce_reg_to_size(&src_reg, 4); | ||
89 | + } | ||
90 | + | ||
91 | __reg_deduce_bounds(dst_reg); | ||
92 | __reg_bound_offset(dst_reg); | ||
93 | return 0; | ||
94 | -- | ||
95 | 2.20.1 | ||
96 | |||