From 087419d17389e8bf61ec793f515f2db1880d8264 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Mon, 18 Feb 2013 09:55:37 -0800 Subject: [PATCH] 3.4-stable patches added patches: printk-fix-buffer-overflow-when-calling-log_prefix-function-from-call_console_drivers.patch --- ...x-function-from-call_console_drivers.patch | 83 +++++++++++++++++++ queue-3.4/series | 1 + 2 files changed, 84 insertions(+) create mode 100644 queue-3.4/printk-fix-buffer-overflow-when-calling-log_prefix-function-from-call_console_drivers.patch create mode 100644 queue-3.4/series diff --git a/queue-3.4/printk-fix-buffer-overflow-when-calling-log_prefix-function-from-call_console_drivers.patch b/queue-3.4/printk-fix-buffer-overflow-when-calling-log_prefix-function-from-call_console_drivers.patch new file mode 100644 index 00000000000..2be3e8058df --- /dev/null +++ b/queue-3.4/printk-fix-buffer-overflow-when-calling-log_prefix-function-from-call_console_drivers.patch @@ -0,0 +1,83 @@ +From Alexandre.Simon@univ-lorraine.fr Mon Feb 18 09:52:16 2013 +From: Alexandre SIMON +Date: Fri, 01 Feb 2013 15:31:54 +0100 +Subject: printk: fix buffer overflow when calling log_prefix function from call_console_drivers +To: Greg Kroah-Hartman , stable@vger.kernel.org +Cc: "Serge E. Hallyn" , Jonathan Nieder , James Morris +Message-ID: <510BD1DA.4010709@univ-lorraine.fr> + +From: Alexandre SIMON + +This patch corrects a buffer overflow in kernels from 3.0 to 3.4 when calling +log_prefix() function from call_console_drivers(). + +This bug existed in previous releases but has been revealed with commit +162a7e7500f9664636e649ba59defe541b7c2c60 (2.6.39 => 3.0) that made changes +about how to allocate memory for early printk buffer (use of memblock_alloc). +It disappears with commit 7ff9554bb578ba02166071d2d487b7fc7d860d62 (3.4 => 3.5) +that does a refactoring of printk buffer management. + +In log_prefix(), the access to "p[0]", "p[1]", "p[2]" or +"simple_strtoul(&p[1], &endp, 10)" may cause a buffer overflow as this +function is called from call_console_drivers by passing "&LOG_BUF(cur_index)" +where the index must be masked to do not exceed the buffer's boundary. + +The trick is to prepare in call_console_drivers() a buffer with the necessary +data (PRI field of syslog message) to be safely evaluated in log_prefix(). + +This patch can be applied to stable kernel branches 3.0.y, 3.2.y and 3.4.y. + +Without this patch, one can freeze a server running this loop from shell : + $ export DUMMY=`cat /dev/urandom | tr -dc '12345AZERTYUIOPQSDFGHJKLMWXCVBNazertyuiopqsdfghjklmwxcvbn' | head -c255` + $ while true do ; echo $DUMMY > /dev/kmsg ; done + +The "server freeze" depends on where memblock_alloc does allocate printk buffer : +if the buffer overflow is inside another kernel allocation the problem may not +be revealed, else the server may hangs up. + +Signed-off-by: Alexandre SIMON +Signed-off-by: Greg Kroah-Hartman + +--- + include/linux/syslog.h | 6 ++++++ + kernel/printk.c | 13 ++++++++++++- + 2 files changed, 18 insertions(+), 1 deletion(-) + +--- a/include/linux/syslog.h ++++ b/include/linux/syslog.h +@@ -47,6 +47,12 @@ + #define SYSLOG_FROM_CALL 0 + #define SYSLOG_FROM_FILE 1 + ++/* ++ * Syslog priority (PRI) maximum length in char : '<[0-9]{1,3}>' ++ * See RFC5424 for details ++*/ ++#define SYSLOG_PRI_MAX_LENGTH 5 ++ + int do_syslog(int type, char __user *buf, int count, bool from_file); + + #endif /* _LINUX_SYSLOG_H */ +--- a/kernel/printk.c ++++ b/kernel/printk.c +@@ -638,8 +638,19 @@ static void call_console_drivers(unsigne + start_print = start; + while (cur_index != end) { + if (msg_level < 0 && ((end - cur_index) > 2)) { ++ /* ++ * prepare buf_prefix, as a contiguous array, ++ * to be processed by log_prefix function ++ */ ++ char buf_prefix[SYSLOG_PRI_MAX_LENGTH+1]; ++ unsigned i; ++ for (i = 0; i < ((end - cur_index)) && (i < SYSLOG_PRI_MAX_LENGTH); i++) { ++ buf_prefix[i] = LOG_BUF(cur_index + i); ++ } ++ buf_prefix[i] = '\0'; /* force '\0' as last string character */ ++ + /* strip log prefix */ +- cur_index += log_prefix(&LOG_BUF(cur_index), &msg_level, NULL); ++ cur_index += log_prefix((const char *)&buf_prefix, &msg_level, NULL); + start_print = cur_index; + } + while (cur_index != end) { diff --git a/queue-3.4/series b/queue-3.4/series new file mode 100644 index 00000000000..097bb826a0c --- /dev/null +++ b/queue-3.4/series @@ -0,0 +1 @@ +printk-fix-buffer-overflow-when-calling-log_prefix-function-from-call_console_drivers.patch -- 2.47.3