lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <1354813571-11253-11-git-send-email-schnhrr@cs.tu-berlin.de>
Date:	Thu,  6 Dec 2012 18:06:07 +0100
From:	Jan H. Schönherr <schnhrr@...tu-berlin.de>
To:	Greg Kroah-Hartman <gregkh@...uxfoundation.org>,
	Kay Sievers <kay@...y.org>
Cc:	linux-kernel@...r.kernel.org, Joe Perches <joe@...ches.com>,
	Andrew Morton <akpm@...ux-foundation.org>,
	Stephen Rothwell <sfr@...b.auug.org.au>,
	Jan H. Schönherr <schnhrr@...tu-berlin.de>
Subject: [PATCH v2 10/14] printk: track previously logged message in log_store()

Centrally track information about the previous message in log_store().

This knowledge allows us to decide immediately whether the current
message is a continuation of the previous message. And if that is so, to
keep the correct log level (continuation records do not have a log level).

Later, this will also allow us to remove the tracking of the previous
message flags throughout the syslog/kmsg formatting code.

Signed-off-by: Jan H. Schönherr <schnhrr@...tu-berlin.de>
---
v2:
- Fixed a bug that could mismerge continuation records, because
  log_store() used "current" as the owner of the message passed in,
  which might be incorrect when used from cont_flush().
- refactored code
- refactored patches
---
 kernel/printk.c | 47 ++++++++++++++++++++++++++++++++++++-----------
 1 file changed, 36 insertions(+), 11 deletions(-)

diff --git a/kernel/printk.c b/kernel/printk.c
index 52ccf93..151c77a 100644
--- a/kernel/printk.c
+++ b/kernel/printk.c
@@ -226,6 +226,10 @@ static size_t syslog_partial;
 static u64 log_first_seq;
 static u32 log_first_idx;
 
+/* information about the last stored message */
+static struct log *log_last_msg;
+static struct task_struct *log_last_owner;
+
 /* index and sequence number of the next record to store in the buffer */
 static u64 log_next_seq;
 static u32 log_next_idx;
@@ -300,18 +304,36 @@ static u32 log_next(u32 idx)
 	return idx + msg->len;
 }
 
+/* return correct level for continuation records */
+static int log_infer_level(struct task_struct *owner, int facility, int level,
+			  enum log_flags flags)
+{
+	if (flags & LOG_PREFIX || level != -1 || !log_last_msg ||
+	    log_last_msg->facility != facility || log_last_owner != owner ||
+	    log_last_msg->flags & LOG_NEWLINE)
+		return level;
+	return log_last_msg->level;
+}
+
 /* insert record into the buffer, discard old ones, update heads */
-static void log_store(int facility, int level,
+static void log_store(struct task_struct *owner, int facility, int level,
 		      enum log_flags flags, u64 ts_nsec,
 		      const char *dict, u16 dict_len,
 		      const char *text, u16 text_len)
 {
 	struct log *msg;
 	u32 size, pad_len;
-
-	/* store something meaningful, when no loglevel was given */
-	if (level == -1)
-		level = default_message_loglevel;
+	int inferred_level;
+
+	/* setup flags/level for storage */
+	inferred_level = log_infer_level(owner, facility, -1, flags);
+	if (inferred_level == -1) {
+		flags |= LOG_PREFIX;
+		if (level == -1)
+			level = default_message_loglevel;
+	} else {
+		level = inferred_level;
+	}
 
 	/* number of '\0' padding bytes to next message */
 	size = sizeof(struct log) + text_len + dict_len;
@@ -329,7 +351,7 @@ static void log_store(int facility, int level,
 		if (free > size + sizeof(struct log))
 			break;
 
-		/* drop old messages until we have enough contiuous space */
+		/* drop old messages until we have enough continuous space */
 		log_first_idx = log_next(log_first_idx);
 		log_first_seq++;
 	}
@@ -363,6 +385,9 @@ static void log_store(int facility, int level,
 	/* insert message */
 	log_next_idx += msg->len;
 	log_next_seq++;
+
+	log_last_owner = owner;
+	log_last_msg = msg;
 }
 
 /* /dev/kmsg - userspace message inject/listen interface */
@@ -1432,8 +1457,8 @@ static void cont_flush(void)
 	if (cont.cons)
 		cont.flags |= LOG_NOCONS;
 
-	log_store(cont.facility, cont.level, cont.flags, cont.ts_nsec, NULL, 0,
-		  cont.buf, cont.len);
+	log_store(cont.owner, cont.facility, cont.level, cont.flags,
+		  cont.ts_nsec, NULL, 0, cont.buf, cont.len);
 
 	/*
 	 * If no fragment of this line ever reached the console or everything
@@ -1550,7 +1575,7 @@ asmlinkage int vprintk_emit(int facility, int level,
 		recursion_bug = 0;
 		printed_len += strlen(recursion_msg);
 		/* emit KERN_CRIT message */
-		log_store(0, 2, LOG_PREFIX|LOG_NEWLINE, 0,
+		log_store(current, 0, 2, LOG_PREFIX | LOG_NEWLINE, 0,
 			  NULL, 0, recursion_msg, printed_len);
 	}
 
@@ -1607,7 +1632,7 @@ asmlinkage int vprintk_emit(int facility, int level,
 
 		/* buffer line if possible, otherwise store it right away */
 		if (!cont_add(facility, level, lflags, text, text_len))
-			log_store(facility, level, lflags, 0,
+			log_store(current, facility, level, lflags, 0,
 				  dict, dictlen, text, text_len);
 	} else {
 		bool stored = false;
@@ -1626,7 +1651,7 @@ asmlinkage int vprintk_emit(int facility, int level,
 		}
 
 		if (!stored)
-			log_store(facility, level, lflags, 0,
+			log_store(current, facility, level, lflags, 0,
 				  dict, dictlen, text, text_len);
 	}
 	printed_len += text_len;
-- 
1.8.0.1.20.g7c65b2e.dirty

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ