From 5027488b26d6102220ca2444aa73c03c035f0277 Mon Sep 17 00:00:00 2001 From: Sona Sarmadi Date: Fri, 3 Feb 2017 08:37:29 +0100 Subject: 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 Signed-off-by: Adrian Dudau --- .../linux/files/ring-buffer-CVE-2016-9754.patch | 95 ++++++++++++++++++++++ recipes-kernel/linux/linux-qoriq_3.12.bbappend | 1 + 2 files changed, 96 insertions(+) create mode 100644 recipes-kernel/linux/files/ring-buffer-CVE-2016-9754.patch 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 @@ +From 5feada97176f05f92088911fa807d30445c6a0c6 Mon Sep 17 00:00:00 2001 +From: "Steven Rostedt (Red Hat)" +Date: Fri, 13 May 2016 09:34:12 -0400 +Subject: [PATCH] ring-buffer: Prevent overflow of size in ring_buffer_resize() + +commit 59643d1535eb220668692a5359de22545af579f6 upstream. + +If the size passed to ring_buffer_resize() is greater than MAX_LONG - BUF_PAGE_SIZE +then the DIV_ROUND_UP() will return zero. + +Here's the details: + + # echo 18014398509481980 > /sys/kernel/debug/tracing/buffer_size_kb + +tracing_entries_write() processes this and converts kb to bytes. + + 18014398509481980 << 10 = 18446744073709547520 + +and this is passed to ring_buffer_resize() as unsigned long size. + + size = DIV_ROUND_UP(size, BUF_PAGE_SIZE); + +Where DIV_ROUND_UP(a, b) is (a + b - 1)/b + +BUF_PAGE_SIZE is 4080 and here + + 18446744073709547520 + 4080 - 1 = 18446744073709551599 + +where 18446744073709551599 is still smaller than 2^64 + + 2^64 - 18446744073709551599 = 17 + +But now 18446744073709551599 / 4080 = 4521260802379792 + +and size = size * 4080 = 18446744073709551360 + +This is checked to make sure its still greater than 2 * 4080, +which it is. + +Then we convert to the number of buffer pages needed. + + nr_page = DIV_ROUND_UP(size, BUF_PAGE_SIZE) + +but this time size is 18446744073709551360 and + + 2^64 - (18446744073709551360 + 4080 - 1) = -3823 + +Thus it overflows and the resulting number is less than 4080, which makes + + 3823 / 4080 = 0 + +an nr_pages is set to this. As we already checked against the minimum that +nr_pages may be, this causes the logic to fail as well, and we crash the +kernel. + +There's no reason to have the two DIV_ROUND_UP() (that's just result of +historical code changes), clean up the code and fix this bug. + +CVE: CVE-2016-9754 +Upstream-Status: Backport + +Fixes: 83f40318dab00 ("ring-buffer: Make removal of ring buffer pages atomic") +Signed-off-by: Steven Rostedt +Signed-off-by: Jiri Slaby +Signed-off-by: Sona Sarmadi +--- + kernel/trace/ring_buffer.c | 9 ++++----- + 1 file changed, 4 insertions(+), 5 deletions(-) + +diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c +index 4940115..f100767 100644 +--- a/kernel/trace/ring_buffer.c ++++ b/kernel/trace/ring_buffer.c +@@ -1645,14 +1645,13 @@ int ring_buffer_resize(struct ring_buffer *buffer, unsigned long size, + !cpumask_test_cpu(cpu_id, buffer->cpumask)) + return size; + +- size = DIV_ROUND_UP(size, BUF_PAGE_SIZE); +- size *= BUF_PAGE_SIZE; ++ nr_pages = DIV_ROUND_UP(size, BUF_PAGE_SIZE); + + /* we need a minimum of two pages */ +- if (size < BUF_PAGE_SIZE * 2) +- size = BUF_PAGE_SIZE * 2; ++ if (nr_pages < 2) ++ nr_pages = 2; + +- nr_pages = DIV_ROUND_UP(size, BUF_PAGE_SIZE); ++ size = nr_pages * BUF_PAGE_SIZE; + + /* + * Don't succeed if resizing is disabled, as a reader might be +-- +1.9.1 + 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 \ file://CVE-2016-3136.patch \ file://CVE-2016-5195.patch \ file://CVE-2016-6480.patch \ + file://ring-buffer-CVE-2016-9754.patch \ " -- cgit v1.2.3-54-g00ecf