[kernel/f15/master] printk: do not mangle valid userspace syslog prefixes
Kyle McMartin
kyle at fedoraproject.org
Tue Mar 29 23:17:27 UTC 2011
commit 1d3db7f8fbb135e9cd6627da77f84bcfc6ef2a81
Author: Kyle McMartin <kyle at redhat.com>
Date: Tue Mar 29 19:17:20 2011 -0400
printk: do not mangle valid userspace syslog prefixes
printk: do not mangle valid userspace syslog prefixes with
/dev/kmsg (#691888)
The patch is upstream in 2.6.39, and Lennart tells me the patch has been
backported for the next Suse release as well.
kernel.spec | 11 +
...ot-mangle-valid-userspace-syslog-prefixes.patch | 214 ++++++++++++++++++++
2 files changed, 225 insertions(+), 0 deletions(-)
---
diff --git a/kernel.spec b/kernel.spec
index 2ababf8..045971e 100644
--- a/kernel.spec
+++ b/kernel.spec
@@ -730,6 +730,8 @@ Patch12207: pci-pcie-links-may-not-get-configured-for-aspm-under-powersave-mode.
Patch12303: dmar-disable-when-ricoh-multifunction.patch
+Patch12305: printk-do-not-mangle-valid-userspace-syslog-prefixes.patch
+
%endif
BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root
@@ -1356,6 +1358,9 @@ ApplyPatch acpi_reboot.patch
# rhbz#605888
ApplyPatch dmar-disable-when-ricoh-multifunction.patch
+# rhbz#691888
+ApplyPatch printk-do-not-mangle-valid-userspace-syslog-prefixes.patch
+
# END OF PATCH APPLICATIONS
%endif
@@ -1964,6 +1969,12 @@ fi
# and build.
%changelog
+* Tue Mar 29 2011 Kyle McMartin <kmcmartin at redhat.com>
+- printk: do not mangle valid userspace syslog prefixes with
+ /dev/kmsg (#691888)
+ - The patch is upstream in 2.6.39, and Lennart tells me the patch has been
+ backported for the next Suse release as well.
+
* Sun Mar 27 2011 Chuck Ebbert <cebbert at redhat.com> 2.6.38.2-8
- Linux 2.6.38.2
- Drop patches merged in 2.6.38.2:
diff --git a/printk-do-not-mangle-valid-userspace-syslog-prefixes.patch b/printk-do-not-mangle-valid-userspace-syslog-prefixes.patch
new file mode 100644
index 0000000..73885ae
--- /dev/null
+++ b/printk-do-not-mangle-valid-userspace-syslog-prefixes.patch
@@ -0,0 +1,214 @@
+From: Kay Sievers <kay.sievers at vrfy.org>
+Date: Sun, 13 Mar 2011 02:19:51 +0000 (+0100)
+Subject: printk: do not mangle valid userspace syslog prefixes
+X-Git-Tag: v2.6.39-rc1~471^2
+X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Ftorvalds%2Flinux-2.6.git;a=commitdiff_plain;h=9d90c8d9cde929cbc575098e825d7c29d9f45054
+
+printk: do not mangle valid userspace syslog prefixes
+
+printk: do not mangle valid userspace syslog prefixes with /dev/kmsg
+
+Log messages passed to the kernel log by using /dev/kmsg or /dev/ttyprintk
+might contain a syslog prefix including the syslog facility value.
+
+This makes printk to recognize these headers properly, extract the real log
+level from it to use, and add the prefix as a proper prefix to the
+log buffer, instead of wrongly printing it as the log message text.
+
+Before:
+ $ echo '<14>text' > /dev/kmsg
+ $ dmesg -r
+ <4>[135159.594810] <14>text
+
+After:
+ $ echo '<14>text' > /dev/kmsg
+ $ dmesg -r
+ <14>[ 50.750654] text
+
+Cc: Lennart Poettering <lennart at poettering.net>
+Signed-off-by: Kay Sievers <kay.sievers at vrfy.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh at suse.de>
+---
+
+diff --git a/kernel/printk.c b/kernel/printk.c
+index 2ddbdc7..5e3d042 100644
+--- a/kernel/printk.c
++++ b/kernel/printk.c
+@@ -499,6 +499,71 @@ static void _call_console_drivers(unsigned start,
+ }
+
+ /*
++ * Parse the syslog header <[0-9]*>. The decimal value represents 32bit, the
++ * lower 3 bit are the log level, the rest are the log facility. In case
++ * userspace passes usual userspace syslog messages to /dev/kmsg or
++ * /dev/ttyprintk, the log prefix might contain the facility. Printk needs
++ * to extract the correct log level for in-kernel processing, and not mangle
++ * the original value.
++ *
++ * If a prefix is found, the length of the prefix is returned. If 'level' is
++ * passed, it will be filled in with the log level without a possible facility
++ * value. If 'special' is passed, the special printk prefix chars are accepted
++ * and returned. If no valid header is found, 0 is returned and the passed
++ * variables are not touched.
++ */
++static size_t log_prefix(const char *p, unsigned int *level, char *special)
++{
++ unsigned int lev = 0;
++ char sp = '\0';
++ size_t len;
++
++ if (p[0] != '<' || !p[1])
++ return 0;
++ if (p[2] == '>') {
++ /* usual single digit level number or special char */
++ switch (p[1]) {
++ case '0' ... '7':
++ lev = p[1] - '0';
++ break;
++ case 'c': /* KERN_CONT */
++ case 'd': /* KERN_DEFAULT */
++ sp = p[1];
++ break;
++ default:
++ return 0;
++ }
++ len = 3;
++ } else {
++ /* multi digit including the level and facility number */
++ char *endp = NULL;
++
++ if (p[1] < '0' && p[1] > '9')
++ return 0;
++
++ lev = (simple_strtoul(&p[1], &endp, 10) & 7);
++ if (endp == NULL || endp[0] != '>')
++ return 0;
++ len = (endp + 1) - p;
++ }
++
++ /* do not accept special char if not asked for */
++ if (sp && !special)
++ return 0;
++
++ if (special) {
++ *special = sp;
++ /* return special char, do not touch level */
++ if (sp)
++ return len;
++ }
++
++ if (level)
++ *level = lev;
++ return len;
++}
++
++/*
+ * Call the console drivers, asking them to write out
+ * log_buf[start] to log_buf[end - 1].
+ * The console_lock must be held.
+@@ -513,13 +578,9 @@ static void call_console_drivers(unsigned start, unsigned end)
+ cur_index = start;
+ start_print = start;
+ while (cur_index != end) {
+- if (msg_level < 0 && ((end - cur_index) > 2) &&
+- LOG_BUF(cur_index + 0) == '<' &&
+- LOG_BUF(cur_index + 1) >= '0' &&
+- LOG_BUF(cur_index + 1) <= '7' &&
+- LOG_BUF(cur_index + 2) == '>') {
+- msg_level = LOG_BUF(cur_index + 1) - '0';
+- cur_index += 3;
++ if (msg_level < 0 && ((end - cur_index) > 2)) {
++ /* strip log prefix */
++ cur_index += log_prefix(&LOG_BUF(cur_index), &msg_level, NULL);
+ start_print = cur_index;
+ }
+ while (cur_index != end) {
+@@ -717,6 +778,8 @@ asmlinkage int vprintk(const char *fmt, va_list args)
+ unsigned long flags;
+ int this_cpu;
+ char *p;
++ size_t plen;
++ char special;
+
+ boot_delay_msec();
+ printk_delay();
+@@ -757,45 +820,52 @@ asmlinkage int vprintk(const char *fmt, va_list args)
+ printed_len += vscnprintf(printk_buf + printed_len,
+ sizeof(printk_buf) - printed_len, fmt, args);
+
+-
+ p = printk_buf;
+
+- /* Do we have a loglevel in the string? */
+- if (p[0] == '<') {
+- unsigned char c = p[1];
+- if (c && p[2] == '>') {
+- switch (c) {
+- case '0' ... '7': /* loglevel */
+- current_log_level = c - '0';
+- /* Fallthrough - make sure we're on a new line */
+- case 'd': /* KERN_DEFAULT */
+- if (!new_text_line) {
+- emit_log_char('\n');
+- new_text_line = 1;
+- }
+- /* Fallthrough - skip the loglevel */
+- case 'c': /* KERN_CONT */
+- p += 3;
+- break;
++ /* Read log level and handle special printk prefix */
++ plen = log_prefix(p, ¤t_log_level, &special);
++ if (plen) {
++ p += plen;
++
++ switch (special) {
++ case 'c': /* Strip <c> KERN_CONT, continue line */
++ plen = 0;
++ break;
++ case 'd': /* Strip <d> KERN_DEFAULT, start new line */
++ plen = 0;
++ default:
++ if (!new_text_line) {
++ emit_log_char('\n');
++ new_text_line = 1;
+ }
+ }
+ }
+
+ /*
+- * Copy the output into log_buf. If the caller didn't provide
+- * appropriate log level tags, we insert them here
++ * Copy the output into log_buf. If the caller didn't provide
++ * the appropriate log prefix, we insert them here
+ */
+- for ( ; *p; p++) {
++ for (; *p; p++) {
+ if (new_text_line) {
+- /* Always output the token */
+- emit_log_char('<');
+- emit_log_char(current_log_level + '0');
+- emit_log_char('>');
+- printed_len += 3;
+ new_text_line = 0;
+
++ if (plen) {
++ /* Copy original log prefix */
++ int i;
++
++ for (i = 0; i < plen; i++)
++ emit_log_char(printk_buf[i]);
++ printed_len += plen;
++ } else {
++ /* Add log prefix */
++ emit_log_char('<');
++ emit_log_char(current_log_level + '0');
++ emit_log_char('>');
++ printed_len += 3;
++ }
++
+ if (printk_time) {
+- /* Follow the token with the time */
++ /* Add the current time stamp */
+ char tbuf[50], *tp;
+ unsigned tlen;
+ unsigned long long t;
More information about the scm-commits
mailing list