diff options
author | Sona Sarmadi <sona.sarmadi@enea.com> | 2017-02-03 08:37:29 +0100 |
---|---|---|
committer | Adrian Dudau <adrian.dudau@enea.com> | 2017-02-03 11:00:14 +0100 |
commit | 5027488b26d6102220ca2444aa73c03c035f0277 (patch) | |
tree | 7fce9cb07194f21275f42dcfad9f6026e5aa9959 | |
parent | 5efb264f10ac2c2753500f862a11b0d9de175930 (diff) | |
download | meta-enea-bsp-ppc-5027488b26d6102220ca2444aa73c03c035f0277.tar.gz |
Kernel: CVE-2016-9754
Integer overflow in ring_buffer_resize()
The ring_buffer_resize function in kernel/trace/ring_buffer.c in the
profiling subsystem in the Linux kernel before 4.6.1 mishandles certain
integer calculations, which allows local users to gain privileges by
writing to the /sys/kernel/debug/tracing/buffer_size_kb file.
References:
https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2016-9754
References to upstream patch:
http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=59643d1535eb220668692a5359de22545af579f6
Signed-off-by: Sona Sarmadi <sona.sarmadi@enea.com>
Signed-off-by: Adrian Dudau <adrian.dudau@enea.com>
-rw-r--r-- | recipes-kernel/linux/files/ring-buffer-CVE-2016-9754.patch | 95 | ||||
-rw-r--r-- | recipes-kernel/linux/linux-qoriq_3.12.bbappend | 1 |
2 files changed, 96 insertions, 0 deletions
diff --git a/recipes-kernel/linux/files/ring-buffer-CVE-2016-9754.patch b/recipes-kernel/linux/files/ring-buffer-CVE-2016-9754.patch new file mode 100644 index 0000000..49d3e42 --- /dev/null +++ b/recipes-kernel/linux/files/ring-buffer-CVE-2016-9754.patch | |||
@@ -0,0 +1,95 @@ | |||
1 | From 5feada97176f05f92088911fa807d30445c6a0c6 Mon Sep 17 00:00:00 2001 | ||
2 | From: "Steven Rostedt (Red Hat)" <rostedt@goodmis.org> | ||
3 | Date: Fri, 13 May 2016 09:34:12 -0400 | ||
4 | Subject: [PATCH] ring-buffer: Prevent overflow of size in ring_buffer_resize() | ||
5 | |||
6 | commit 59643d1535eb220668692a5359de22545af579f6 upstream. | ||
7 | |||
8 | If the size passed to ring_buffer_resize() is greater than MAX_LONG - BUF_PAGE_SIZE | ||
9 | then the DIV_ROUND_UP() will return zero. | ||
10 | |||
11 | Here's the details: | ||
12 | |||
13 | # echo 18014398509481980 > /sys/kernel/debug/tracing/buffer_size_kb | ||
14 | |||
15 | tracing_entries_write() processes this and converts kb to bytes. | ||
16 | |||
17 | 18014398509481980 << 10 = 18446744073709547520 | ||
18 | |||
19 | and this is passed to ring_buffer_resize() as unsigned long size. | ||
20 | |||
21 | size = DIV_ROUND_UP(size, BUF_PAGE_SIZE); | ||
22 | |||
23 | Where DIV_ROUND_UP(a, b) is (a + b - 1)/b | ||
24 | |||
25 | BUF_PAGE_SIZE is 4080 and here | ||
26 | |||
27 | 18446744073709547520 + 4080 - 1 = 18446744073709551599 | ||
28 | |||
29 | where 18446744073709551599 is still smaller than 2^64 | ||
30 | |||
31 | 2^64 - 18446744073709551599 = 17 | ||
32 | |||
33 | But now 18446744073709551599 / 4080 = 4521260802379792 | ||
34 | |||
35 | and size = size * 4080 = 18446744073709551360 | ||
36 | |||
37 | This is checked to make sure its still greater than 2 * 4080, | ||
38 | which it is. | ||
39 | |||
40 | Then we convert to the number of buffer pages needed. | ||
41 | |||
42 | nr_page = DIV_ROUND_UP(size, BUF_PAGE_SIZE) | ||
43 | |||
44 | but this time size is 18446744073709551360 and | ||
45 | |||
46 | 2^64 - (18446744073709551360 + 4080 - 1) = -3823 | ||
47 | |||
48 | Thus it overflows and the resulting number is less than 4080, which makes | ||
49 | |||
50 | 3823 / 4080 = 0 | ||
51 | |||
52 | an nr_pages is set to this. As we already checked against the minimum that | ||
53 | nr_pages may be, this causes the logic to fail as well, and we crash the | ||
54 | kernel. | ||
55 | |||
56 | There's no reason to have the two DIV_ROUND_UP() (that's just result of | ||
57 | historical code changes), clean up the code and fix this bug. | ||
58 | |||
59 | CVE: CVE-2016-9754 | ||
60 | Upstream-Status: Backport | ||
61 | |||
62 | Fixes: 83f40318dab00 ("ring-buffer: Make removal of ring buffer pages atomic") | ||
63 | Signed-off-by: Steven Rostedt <rostedt@goodmis.org> | ||
64 | Signed-off-by: Jiri Slaby <jslaby@suse.cz> | ||
65 | Signed-off-by: Sona Sarmadi <sona.sarmadi@enea.com> | ||
66 | --- | ||
67 | kernel/trace/ring_buffer.c | 9 ++++----- | ||
68 | 1 file changed, 4 insertions(+), 5 deletions(-) | ||
69 | |||
70 | diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c | ||
71 | index 4940115..f100767 100644 | ||
72 | --- a/kernel/trace/ring_buffer.c | ||
73 | +++ b/kernel/trace/ring_buffer.c | ||
74 | @@ -1645,14 +1645,13 @@ int ring_buffer_resize(struct ring_buffer *buffer, unsigned long size, | ||
75 | !cpumask_test_cpu(cpu_id, buffer->cpumask)) | ||
76 | return size; | ||
77 | |||
78 | - size = DIV_ROUND_UP(size, BUF_PAGE_SIZE); | ||
79 | - size *= BUF_PAGE_SIZE; | ||
80 | + nr_pages = DIV_ROUND_UP(size, BUF_PAGE_SIZE); | ||
81 | |||
82 | /* we need a minimum of two pages */ | ||
83 | - if (size < BUF_PAGE_SIZE * 2) | ||
84 | - size = BUF_PAGE_SIZE * 2; | ||
85 | + if (nr_pages < 2) | ||
86 | + nr_pages = 2; | ||
87 | |||
88 | - nr_pages = DIV_ROUND_UP(size, BUF_PAGE_SIZE); | ||
89 | + size = nr_pages * BUF_PAGE_SIZE; | ||
90 | |||
91 | /* | ||
92 | * Don't succeed if resizing is disabled, as a reader might be | ||
93 | -- | ||
94 | 1.9.1 | ||
95 | |||
diff --git a/recipes-kernel/linux/linux-qoriq_3.12.bbappend b/recipes-kernel/linux/linux-qoriq_3.12.bbappend index 596cd1b..be8cf93 100644 --- a/recipes-kernel/linux/linux-qoriq_3.12.bbappend +++ b/recipes-kernel/linux/linux-qoriq_3.12.bbappend | |||
@@ -9,5 +9,6 @@ SRC_URI += "file://ppp-CVE-2015-8569.patch \ | |||
9 | file://CVE-2016-3136.patch \ | 9 | file://CVE-2016-3136.patch \ |
10 | file://CVE-2016-5195.patch \ | 10 | file://CVE-2016-5195.patch \ |
11 | file://CVE-2016-6480.patch \ | 11 | file://CVE-2016-6480.patch \ |
12 | file://ring-buffer-CVE-2016-9754.patch \ | ||
12 | " | 13 | " |
13 | 14 | ||