diff options
author | Kay Sievers <kay@vrfy.org> | 2012-07-16 21:35:29 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-07-16 21:35:29 -0400 |
commit | 70498253186586e5dca7bc3ebd3415203b059fbc (patch) | |
tree | 7039fd24627aff100b3fc5ddf97e9b27dae9b8b5 /kernel | |
parent | 28a78e46f04ac5c4952533f2938a18699f207004 (diff) |
kmsg - properly print over-long continuation lines
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>
Cc: stable <stable@vger.kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/printk.c | 33 |
1 files changed, 19 insertions, 14 deletions
diff --git a/kernel/printk.c b/kernel/printk.c index 177fa49357a5..d87ca5c6a989 100644 --- a/kernel/printk.c +++ b/kernel/printk.c | |||
@@ -235,7 +235,8 @@ static u32 log_next_idx; | |||
235 | static u64 clear_seq; | 235 | static u64 clear_seq; |
236 | static u32 clear_idx; | 236 | static u32 clear_idx; |
237 | 237 | ||
238 | #define LOG_LINE_MAX 1024 | 238 | #define PREFIX_MAX 32 |
239 | #define LOG_LINE_MAX 1024 - PREFIX_MAX | ||
239 | 240 | ||
240 | /* record buffer */ | 241 | /* record buffer */ |
241 | #if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) | 242 | #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, | |||
876 | 877 | ||
877 | if (buf) { | 878 | if (buf) { |
878 | if (print_prefix(msg, syslog, NULL) + | 879 | if (print_prefix(msg, syslog, NULL) + |
879 | text_len + 1>= size - len) | 880 | text_len + 1 >= size - len) |
880 | break; | 881 | break; |
881 | 882 | ||
882 | if (prefix) | 883 | if (prefix) |
@@ -907,7 +908,7 @@ static int syslog_print(char __user *buf, int size) | |||
907 | struct log *msg; | 908 | struct log *msg; |
908 | int len = 0; | 909 | int len = 0; |
909 | 910 | ||
910 | text = kmalloc(LOG_LINE_MAX, GFP_KERNEL); | 911 | text = kmalloc(LOG_LINE_MAX + PREFIX_MAX, GFP_KERNEL); |
911 | if (!text) | 912 | if (!text) |
912 | return -ENOMEM; | 913 | return -ENOMEM; |
913 | 914 | ||
@@ -930,7 +931,8 @@ static int syslog_print(char __user *buf, int size) | |||
930 | 931 | ||
931 | skip = syslog_partial; | 932 | skip = syslog_partial; |
932 | msg = log_from_idx(syslog_idx); | 933 | msg = log_from_idx(syslog_idx); |
933 | n = msg_print_text(msg, syslog_prev, true, text, LOG_LINE_MAX); | 934 | n = msg_print_text(msg, syslog_prev, true, text, |
935 | LOG_LINE_MAX + PREFIX_MAX); | ||
934 | if (n - syslog_partial <= size) { | 936 | if (n - syslog_partial <= size) { |
935 | /* message fits into buffer, move forward */ | 937 | /* message fits into buffer, move forward */ |
936 | syslog_idx = log_next(syslog_idx); | 938 | syslog_idx = log_next(syslog_idx); |
@@ -969,7 +971,7 @@ static int syslog_print_all(char __user *buf, int size, bool clear) | |||
969 | char *text; | 971 | char *text; |
970 | int len = 0; | 972 | int len = 0; |
971 | 973 | ||
972 | text = kmalloc(LOG_LINE_MAX, GFP_KERNEL); | 974 | text = kmalloc(LOG_LINE_MAX + PREFIX_MAX, GFP_KERNEL); |
973 | if (!text) | 975 | if (!text) |
974 | return -ENOMEM; | 976 | return -ENOMEM; |
975 | 977 | ||
@@ -1022,7 +1024,8 @@ static int syslog_print_all(char __user *buf, int size, bool clear) | |||
1022 | struct log *msg = log_from_idx(idx); | 1024 | struct log *msg = log_from_idx(idx); |
1023 | int textlen; | 1025 | int textlen; |
1024 | 1026 | ||
1025 | textlen = msg_print_text(msg, prev, true, text, LOG_LINE_MAX); | 1027 | textlen = msg_print_text(msg, prev, true, text, |
1028 | LOG_LINE_MAX + PREFIX_MAX); | ||
1026 | if (textlen < 0) { | 1029 | if (textlen < 0) { |
1027 | len = textlen; | 1030 | len = textlen; |
1028 | break; | 1031 | break; |
@@ -1367,15 +1370,15 @@ static struct cont { | |||
1367 | bool flushed:1; /* buffer sealed and committed */ | 1370 | bool flushed:1; /* buffer sealed and committed */ |
1368 | } cont; | 1371 | } cont; |
1369 | 1372 | ||
1370 | static void cont_flush(void) | 1373 | static void cont_flush(enum log_flags flags) |
1371 | { | 1374 | { |
1372 | if (cont.flushed) | 1375 | if (cont.flushed) |
1373 | return; | 1376 | return; |
1374 | if (cont.len == 0) | 1377 | if (cont.len == 0) |
1375 | return; | 1378 | return; |
1376 | 1379 | ||
1377 | log_store(cont.facility, cont.level, LOG_NOCONS, cont.ts_nsec, | 1380 | log_store(cont.facility, cont.level, LOG_NOCONS | flags, |
1378 | NULL, 0, cont.buf, cont.len); | 1381 | cont.ts_nsec, NULL, 0, cont.buf, cont.len); |
1379 | 1382 | ||
1380 | cont.flushed = true; | 1383 | cont.flushed = true; |
1381 | } | 1384 | } |
@@ -1386,7 +1389,8 @@ static bool cont_add(int facility, int level, const char *text, size_t len) | |||
1386 | return false; | 1389 | return false; |
1387 | 1390 | ||
1388 | if (cont.len + len > sizeof(cont.buf)) { | 1391 | if (cont.len + len > sizeof(cont.buf)) { |
1389 | cont_flush(); | 1392 | /* the line gets too long, split it up in separate records */ |
1393 | cont_flush(LOG_CONT); | ||
1390 | return false; | 1394 | return false; |
1391 | } | 1395 | } |
1392 | 1396 | ||
@@ -1522,7 +1526,7 @@ asmlinkage int vprintk_emit(int facility, int level, | |||
1522 | * or another task also prints continuation lines. | 1526 | * or another task also prints continuation lines. |
1523 | */ | 1527 | */ |
1524 | if (cont.len && (lflags & LOG_PREFIX || cont.owner != current)) | 1528 | if (cont.len && (lflags & LOG_PREFIX || cont.owner != current)) |
1525 | cont_flush(); | 1529 | cont_flush(0); |
1526 | 1530 | ||
1527 | /* buffer line if possible, otherwise store it right away */ | 1531 | /* buffer line if possible, otherwise store it right away */ |
1528 | if (!cont_add(facility, level, text, text_len)) | 1532 | if (!cont_add(facility, level, text, text_len)) |
@@ -1540,7 +1544,7 @@ asmlinkage int vprintk_emit(int facility, int level, | |||
1540 | if (cont.len && cont.owner == current) { | 1544 | if (cont.len && cont.owner == current) { |
1541 | if (!(lflags & LOG_PREFIX)) | 1545 | if (!(lflags & LOG_PREFIX)) |
1542 | stored = cont_add(facility, level, text, text_len); | 1546 | stored = cont_add(facility, level, text, text_len); |
1543 | cont_flush(); | 1547 | cont_flush(0); |
1544 | } | 1548 | } |
1545 | 1549 | ||
1546 | if (!stored) | 1550 | if (!stored) |
@@ -1633,7 +1637,8 @@ EXPORT_SYMBOL(printk); | |||
1633 | 1637 | ||
1634 | #else | 1638 | #else |
1635 | 1639 | ||
1636 | #define LOG_LINE_MAX 0 | 1640 | #define LOG_LINE_MAX 0 |
1641 | #define PREFIX_MAX 0 | ||
1637 | static struct cont { | 1642 | static struct cont { |
1638 | size_t len; | 1643 | size_t len; |
1639 | size_t cons; | 1644 | size_t cons; |
@@ -1938,7 +1943,7 @@ static enum log_flags console_prev; | |||
1938 | */ | 1943 | */ |
1939 | void console_unlock(void) | 1944 | void console_unlock(void) |
1940 | { | 1945 | { |
1941 | static char text[LOG_LINE_MAX]; | 1946 | static char text[LOG_LINE_MAX + PREFIX_MAX]; |
1942 | static u64 seen_seq; | 1947 | static u64 seen_seq; |
1943 | unsigned long flags; | 1948 | unsigned long flags; |
1944 | bool wake_klogd = false; | 1949 | bool wake_klogd = false; |