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-next>] [day] [month] [year] [list]
Date:	Fri, 30 Nov 2012 17:11:07 +0000
From:	Seiji Aguchi <seiji.aguchi@....com>
To:	"linux-kernel@...r.kernel.org" <linux-kernel@...r.kernel.org>,
	"akpm@...ux-foundation.org" <akpm@...ux-foundation.org>,
	"joe@...ches.com" <joe@...ches.com>,
	"gregkh@...uxfoundation.org" <gregkh@...uxfoundation.org>,
	"kay@...y.org" <kay@...y.org>,
	"jim.cromie@...il.com" <jim.cromie@...il.com>,
	"mingo@...e.hu" <mingo@...e.hu>,
	"sboyd@...eaurora.org" <sboyd@...eaurora.org>,
	"jason.wessel@...driver.com" <jason.wessel@...driver.com>,
	"a.p.zijlstra@...llo.nl" <a.p.zijlstra@...llo.nl>,
	"rostedt@...dmis.org" <rostedt@...dmis.org>
CC:	"dle-develop@...ts.sourceforge.net" 
	<dle-develop@...ts.sourceforge.net>,
	Satoru Moriya <satoru.moriya@....com>
Subject: [PATCH] Avoid dead lock of console related locks in panic case

[Issue]

If one cpu ,which is taking a logbuf_lock or console_sem, 
receive IPI/NMI from a panicked cpu via smp_send_stop(),
the panicked cpu hangs up in subsequent kmsg_dump()/printk()
because logbuf_lock and console_sem are taken in the function calls.

This causes a console blank and users can't see panic messages.

[Solution]

this patch introduces a logic initializing logbuf_lock and console_sem
just after smp_send_stop() to avoid dead locks above.

Signed-off-by: Seiji Aguchi <seiji.aguchi@....com>
---
 include/linux/printk.h |    5 +++++
 kernel/panic.c         |    1 +
 kernel/printk.c        |   17 +++++++++++++++++
 lib/bust_spinlocks.c   |   21 ++++++++++++++++++---
 4 files changed, 41 insertions(+), 3 deletions(-)

diff --git a/include/linux/printk.h b/include/linux/printk.h
index 9afc01e..ffd3e55 100644
--- a/include/linux/printk.h
+++ b/include/linux/printk.h
@@ -139,6 +139,7 @@ extern int kptr_restrict;
 
 void log_buf_kexec_setup(void);
 void __init setup_log_buf(int early);
+void zap_locks_force(void);
 #else
 static inline __printf(1, 0)
 int vprintk(const char *s, va_list args)
@@ -172,6 +173,10 @@ static inline void log_buf_kexec_setup(void)
 static inline void setup_log_buf(int early)
 {
 }
+
+static inline void zap_locks_force(void)
+{
+}
 #endif
 
 extern void dump_stack(void) __cold;
diff --git a/kernel/panic.c b/kernel/panic.c
index e1b2822..c27e58e 100644
--- a/kernel/panic.c
+++ b/kernel/panic.c
@@ -122,6 +122,7 @@ void panic(const char *fmt, ...)
 	 * situation.
 	 */
 	smp_send_stop();
+	bust_spinlocks(2);
 
 	kmsg_dump(KMSG_DUMP_PANIC);
 
diff --git a/kernel/printk.c b/kernel/printk.c
index 2d607f4..a6fa638 100644
--- a/kernel/printk.c
+++ b/kernel/printk.c
@@ -1278,6 +1278,23 @@ static void call_console_drivers(int level, const char *text, size_t len)
 }
 
 /*
+ * Zap console related locks in panic situation.
+ * It should be called by bust_spinlocks().
+ */
+void zap_locks_force(void)
+{
+	debug_locks_off();
+
+	/* If a crash is occurring, make sure we can't deadlock */
+	if (raw_spin_is_locked(&logbuf_lock))
+		raw_spin_lock_init(&logbuf_lock);
+
+	/* And make sure that we print immediately */
+	if (is_console_locked())
+		sema_init(&console_sem, 1);
+}
+
+/*
  * Zap console related locks when oopsing. Only zap at most once
  * every 10 seconds, to leave time for slow consoles to print a
  * full oops.
diff --git a/lib/bust_spinlocks.c b/lib/bust_spinlocks.c
index 9681d54..ffa1c64 100644
--- a/lib/bust_spinlocks.c
+++ b/lib/bust_spinlocks.c
@@ -13,19 +13,34 @@
 #include <linux/wait.h>
 #include <linux/vt_kern.h>
 #include <linux/console.h>
+#include <linux/printk.h>
 
 
+/*
+ * yes = 0: make sure that messages are printed to console immediately.
+ * yes = 1: avoid a recursive lock on a single cpu in a panic case.
+ * yes = 2: avoid a deadlock after stopping cpus by smp_send_stop()
+ *          in a panic case.
+ */
 void __attribute__((weak)) bust_spinlocks(int yes)
 {
-	if (yes) {
-		++oops_in_progress;
-	} else {
+	switch (yes) {
+	case 0:
 #ifdef CONFIG_VT
 		unblank_screen();
 #endif
 		console_unblank();
 		if (--oops_in_progress == 0)
 			wake_up_klogd();
+		break;
+	case 1:
+		++oops_in_progress;
+		break;
+	case 2:
+		zap_locks_force();
+		break;
+	default:
+		break;
 	}
 }
 
-- 
1.7.1

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