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]
Date:	Fri, 20 Dec 2013 18:41:37 +0900
From:	Yoshihiro YUNOMAE <yoshihiro.yunomae.ez@...achi.com>
To:	linux-kernel@...r.kernel.org
Cc:	Eiichi Tsukata <eiichi.tsukata.xh@...achi.com>,
	Frederic Weisbecker <fweisbec@...il.com>,
	Kay Sievers <kay@...y.org>, Tejun Heo <tj@...nel.org>,
	yrl.pp-manager.tt@...achi.com,
	Masami Hiramatsu <masami.hiramatsu.pt@...achi.com>,
	Joe Perches <joe@...ches.com>,
	Andrew Morton <akpm@...ux-foundation.org>,
	Hidehiro Kawai <hidehiro.kawai.ez@...achi.com>
Subject: [PATCH 1/2] printk: Add dictionary information in structure cont

Add dictionary information in structure cont.
Dictionary information is added when a driver uses structured printk, and the
information is shown in /dev/kmsg. Current kernel directly stores the
information to log_buf. This patch stores the dict information in structure cont
first, then the information in cont is stored to log_buf.

Signed-off-by: Yoshihiro YUNOMAE <yoshihiro.yunomae.ez@...achi.com>
Cc: Kay Sievers <kay@...y.org>
Cc: Andrew Morton <akpm@...ux-foundation.org>
Cc: Joe Perches <joe@...ches.com>
Cc: Tejun Heo <tj@...nel.org>
Cc: Frederic Weisbecker <fweisbec@...il.com>
Cc: linux-kernel@...r.kernel.org
---
 kernel/printk/printk.c |   70 ++++++++++++++++++++++++++++++++----------------
 1 file changed, 47 insertions(+), 23 deletions(-)

diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
index be7c86b..c3662e6 100644
--- a/kernel/printk/printk.c
+++ b/kernel/printk/printk.c
@@ -1391,8 +1391,10 @@ static inline void printk_delay(void)
  * reached the console in case of a kernel crash.
  */
 static struct cont {
-	char buf[LOG_LINE_MAX];
-	size_t len;			/* length == 0 means unused buffer */
+	char text[LOG_LINE_MAX];
+	size_t text_len;		/* length == 0 means unused buffer */
+	char dict[LOG_LINE_MAX];	/* stores dict */
+	size_t dict_len;		/* 0 means dict is unstored */
 	size_t cons;			/* bytes written to console */
 	struct task_struct *owner;	/* task of first print*/
 	u64 ts_nsec;			/* time of first print */
@@ -1406,7 +1408,7 @@ static void cont_flush(enum log_flags flags)
 {
 	if (cont.flushed)
 		return;
-	if (cont.len == 0)
+	if (cont.text_len == 0)
 		return;
 
 	if (cont.cons) {
@@ -1416,7 +1418,7 @@ static void cont_flush(enum log_flags flags)
 		 * line. LOG_NOCONS suppresses a duplicated output.
 		 */
 		log_store(cont.facility, cont.level, flags | LOG_NOCONS,
-			  cont.ts_nsec, NULL, 0, cont.buf, cont.len);
+			  cont.ts_nsec, NULL, 0, cont.text, cont.text_len);
 		cont.flags = flags;
 		cont.flushed = true;
 	} else {
@@ -1425,23 +1427,32 @@ static void cont_flush(enum log_flags flags)
 		 * just submit it to the store and free the buffer.
 		 */
 		log_store(cont.facility, cont.level, flags, 0,
-			  NULL, 0, cont.buf, cont.len);
-		cont.len = 0;
+			  NULL, 0, cont.text, cont.text_len);
+		cont.text_len = 0;
 	}
 }
 
-static bool cont_add(int facility, int level, const char *text, size_t len)
+static void cont_dict_add(const char *dict, size_t dict_len)
 {
-	if (cont.len && cont.flushed)
+	if (cont.dict_len + dict_len > sizeof(cont.dict))
+		return;
+
+	memcpy(cont.dict + cont.dict_len, dict, dict_len);
+	cont.dict_len += dict_len;
+}
+
+static bool cont_add(int facility, int level, const char *text, size_t text_len)
+{
+	if (cont.text_len && cont.flushed)
 		return false;
 
-	if (cont.len + len > sizeof(cont.buf)) {
+	if (cont.text_len + text_len > sizeof(cont.text)) {
 		/* the line gets too long, split it up in separate records */
 		cont_flush(LOG_CONT);
 		return false;
 	}
 
-	if (!cont.len) {
+	if (!cont.text_len) {
 		cont.facility = facility;
 		cont.level = level;
 		cont.owner = current;
@@ -1451,10 +1462,10 @@ static bool cont_add(int facility, int level, const char *text, size_t len)
 		cont.flushed = false;
 	}
 
-	memcpy(cont.buf + cont.len, text, len);
-	cont.len += len;
+	memcpy(cont.text + cont.text_len, text, text_len);
+	cont.text_len += text_len;
 
-	if (cont.len > (sizeof(cont.buf) * 80) / 100)
+	if (cont.text_len > (sizeof(cont.text) * 80) / 100)
 		cont_flush(LOG_CONT);
 
 	return true;
@@ -1470,20 +1481,20 @@ static size_t cont_print_text(char *text, size_t size)
 		size -= textlen;
 	}
 
-	len = cont.len - cont.cons;
+	len = cont.text_len - cont.cons;
 	if (len > 0) {
 		if (len+1 > size)
 			len = size-1;
-		memcpy(text + textlen, cont.buf + cont.cons, len);
+		memcpy(text + textlen, cont.text + cont.cons, len);
 		textlen += len;
-		cont.cons = cont.len;
+		cont.cons = cont.text_len;
 	}
 
 	if (cont.flushed) {
 		if (cont.flags & LOG_NEWLINE)
 			text[textlen++] = '\n';
 		/* got everything, release buffer */
-		cont.len = 0;
+		cont.text_len = 0;
 	}
 	return textlen;
 }
@@ -1576,21 +1587,29 @@ asmlinkage int vprintk_emit(int facility, int level,
 	if (level == -1)
 		level = default_message_loglevel;
 
-	if (dict)
+	if (dict) {
 		lflags |= LOG_PREFIX|LOG_NEWLINE;
 
+		/* Another task is trying to output a message */
+		if (cont.text_len && cont.owner != current)
+			cont_flush(LOG_NEWLINE);
+
+		cont_dict_add(dict, dictlen);
+	}
+
 	if (!(lflags & LOG_NEWLINE)) {
 		/*
 		 * Flush the conflicting buffer. An earlier newline was missing,
 		 * or another task also prints continuation lines.
 		 */
-		if (cont.len && (lflags & LOG_PREFIX || cont.owner != current))
+		if (cont.text_len &&
+		    (lflags & LOG_PREFIX || cont.owner != current))
 			cont_flush(LOG_NEWLINE);
 
 		/* buffer line if possible, otherwise store it right away */
 		if (!cont_add(facility, level, text, text_len))
 			log_store(facility, level, lflags | LOG_CONT, 0,
-				  dict, dictlen, text, text_len);
+				  NULL, 0, text, text_len);
 	} else {
 		bool stored = false;
 
@@ -1600,7 +1619,7 @@ asmlinkage int vprintk_emit(int facility, int level,
 		 * there was a race with interrupts (prefix == true) then just
 		 * flush it out and store this line separately.
 		 */
-		if (cont.len && cont.owner == current) {
+		if (cont.text_len && cont.owner == current) {
 			if (!(lflags & LOG_PREFIX))
 				stored = cont_add(facility, level, text, text_len);
 			cont_flush(LOG_NEWLINE);
@@ -1608,7 +1627,12 @@ asmlinkage int vprintk_emit(int facility, int level,
 
 		if (!stored)
 			log_store(facility, level, lflags, 0,
-				  dict, dictlen, text, text_len);
+				  cont.dict, cont.dict_len, text, text_len);
+		/*
+		 * Structured printk always starts a new line now, so clear
+		 * current dictionary information for next structured printk.
+		 */
+		cont.dict_len = 0;
 	}
 	printed_len += text_len;
 
@@ -1974,7 +1998,7 @@ static void console_cont_flush(char *text, size_t size)
 
 	raw_spin_lock_irqsave(&logbuf_lock, flags);
 
-	if (!cont.len)
+	if (!cont.text_len)
 		goto out;
 
 	/*

--
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