]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
kmsg - properly print over-long continuation lines
authorKay Sievers <kay@vrfy.org>
Tue, 17 Jul 2012 01:35:29 +0000 (18:35 -0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 9 Aug 2012 15:22:54 +0000 (08:22 -0700)
commit 70498253186586e5dca7bc3ebd3415203b059fbc upstream.

Reserve PREFIX_MAX bytes in the LOG_LINE_MAX line when buffering a
continuation line, to be able to properly prefix the LOG_LINE_MAX
line with the syslog prefix and timestamp when printing it.

Reported-By: Dave Jones <davej@redhat.com>
Signed-off-by: Kay Sievers <kay@vrfy.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
kernel/printk.c

index ac4bc9e79465ed6cf416d9694f8ddc463e2e77ab..21bea76a9fff53fe963071919c43da92778cb829 100644 (file)
@@ -235,7 +235,8 @@ static u32 log_next_idx;
 static u64 clear_seq;
 static u32 clear_idx;
 
-#define LOG_LINE_MAX 1024
+#define PREFIX_MAX             32
+#define LOG_LINE_MAX           1024 - PREFIX_MAX
 
 /* record buffer */
 #if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)
@@ -876,7 +877,7 @@ static size_t msg_print_text(const struct log *msg, enum log_flags prev,
 
                if (buf) {
                        if (print_prefix(msg, syslog, NULL) +
-                           text_len + 1>= size - len)
+                           text_len + 1 >= size - len)
                                break;
 
                        if (prefix)
@@ -907,7 +908,7 @@ static int syslog_print(char __user *buf, int size)
        struct log *msg;
        int len = 0;
 
-       text = kmalloc(LOG_LINE_MAX, GFP_KERNEL);
+       text = kmalloc(LOG_LINE_MAX + PREFIX_MAX, GFP_KERNEL);
        if (!text)
                return -ENOMEM;
 
@@ -930,7 +931,8 @@ static int syslog_print(char __user *buf, int size)
 
                skip = syslog_partial;
                msg = log_from_idx(syslog_idx);
-               n = msg_print_text(msg, syslog_prev, true, text, LOG_LINE_MAX);
+               n = msg_print_text(msg, syslog_prev, true, text,
+                                  LOG_LINE_MAX + PREFIX_MAX);
                if (n - syslog_partial <= size) {
                        /* message fits into buffer, move forward */
                        syslog_idx = log_next(syslog_idx);
@@ -969,7 +971,7 @@ static int syslog_print_all(char __user *buf, int size, bool clear)
        char *text;
        int len = 0;
 
-       text = kmalloc(LOG_LINE_MAX, GFP_KERNEL);
+       text = kmalloc(LOG_LINE_MAX + PREFIX_MAX, GFP_KERNEL);
        if (!text)
                return -ENOMEM;
 
@@ -1022,7 +1024,8 @@ static int syslog_print_all(char __user *buf, int size, bool clear)
                        struct log *msg = log_from_idx(idx);
                        int textlen;
 
-                       textlen = msg_print_text(msg, prev, true, text, LOG_LINE_MAX);
+                       textlen = msg_print_text(msg, prev, true, text,
+                                                LOG_LINE_MAX + PREFIX_MAX);
                        if (textlen < 0) {
                                len = textlen;
                                break;
@@ -1352,15 +1355,15 @@ static struct cont {
        bool flushed:1;                 /* buffer sealed and committed */
 } cont;
 
-static void cont_flush(void)
+static void cont_flush(enum log_flags flags)
 {
        if (cont.flushed)
                return;
        if (cont.len == 0)
                return;
 
-       log_store(cont.facility, cont.level, LOG_NOCONS, cont.ts_nsec,
-                 NULL, 0, cont.buf, cont.len);
+       log_store(cont.facility, cont.level, LOG_NOCONS | flags,
+                 cont.ts_nsec, NULL, 0, cont.buf, cont.len);
 
        cont.flushed = true;
 }
@@ -1371,7 +1374,8 @@ static bool cont_add(int facility, int level, const char *text, size_t len)
                return false;
 
        if (cont.len + len > sizeof(cont.buf)) {
-               cont_flush();
+               /* the line gets too long, split it up in separate records */
+               cont_flush(LOG_CONT);
                return false;
        }
 
@@ -1507,7 +1511,7 @@ asmlinkage int vprintk_emit(int facility, int level,
                 * or another task also prints continuation lines.
                 */
                if (cont.len && (lflags & LOG_PREFIX || cont.owner != current))
-                       cont_flush();
+                       cont_flush(0);
 
                /* buffer line if possible, otherwise store it right away */
                if (!cont_add(facility, level, text, text_len))
@@ -1525,7 +1529,7 @@ asmlinkage int vprintk_emit(int facility, int level,
                if (cont.len && cont.owner == current) {
                        if (!(lflags & LOG_PREFIX))
                                stored = cont_add(facility, level, text, text_len);
-                       cont_flush();
+                       cont_flush(0);
                }
 
                if (!stored)
@@ -1618,7 +1622,8 @@ EXPORT_SYMBOL(printk);
 
 #else
 
-#define LOG_LINE_MAX 0
+#define LOG_LINE_MAX           0
+#define PREFIX_MAX             0
 static struct cont {
        size_t len;
        size_t cons;
@@ -1923,7 +1928,7 @@ static enum log_flags console_prev;
  */
 void console_unlock(void)
 {
-       static char text[LOG_LINE_MAX];
+       static char text[LOG_LINE_MAX + PREFIX_MAX];
        static u64 seen_seq;
        unsigned long flags;
        bool wake_klogd = false;