--- /dev/null
+From Alexandre.Simon@univ-lorraine.fr Mon Feb 18 09:52:16 2013
+From: Alexandre SIMON <Alexandre.Simon@univ-lorraine.fr>
+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 <gregkh@linuxfoundation.org>, stable@vger.kernel.org
+Cc: "Serge E. Hallyn" <serge@hallyn.com>, Jonathan Nieder <jrnieder@gmail.com>, James Morris <jmorris@namei.org>
+Message-ID: <510BD1DA.4010709@univ-lorraine.fr>
+
+From: Alexandre SIMON <Alexandre.Simon@univ-lorraine.fr>
+
+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 <Alexandre.Simon@univ-lorraine.fr>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ 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
+@@ -633,8 +633,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) {