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: <1263481176-1897-34-git-send-email-jason.wessel@windriver.com>
Date:	Thu, 14 Jan 2010 08:59:29 -0600
From:	Jason Wessel <jason.wessel@...driver.com>
To:	linux-kernel@...r.kernel.org
Cc:	kgdb-bugreport@...ts.sourceforge.net, mingo@...e.hu,
	Jason Wessel <jason.wessel@...driver.com>,
	David Airlie <airlied@...ux.ie>,
	Jesse Barnes <jbarnes@...tuousgeek.org>
Subject: [PATCH 33/40] kms,kdb: Force unblank a console device

The kgdboc pre exception handler must atomically save the state of the
existing VC console and activate it, if it is blanked.

Before restoring the kernel to a running state, the kgdboc post
exception handler will restore the state of the VC variables that got
changed while atomic.

Helper macros were added to allow kms code to declare debugger safe
mutexes which can be used so long as the debugger restores the state
before resuming.

CC: David Airlie <airlied@...ux.ie>
CC: Jesse Barnes <jbarnes@...tuousgeek.org>
Signed-off-by: Jason Wessel <jason.wessel@...driver.com>
---
 drivers/serial/kgdboc.c       |   26 ++++++++++++----
 drivers/video/console/fbcon.c |    7 ++++
 include/linux/kgdb.h          |   19 ++++++++++++
 kernel/debug/Makefile         |    1 +
 kernel/debug/debug_core.c     |    1 +
 kernel/debug/kms_hooks.c      |   62 +++++++++++++++++++++++++++++++++++++++++
 6 files changed, 109 insertions(+), 7 deletions(-)
 create mode 100644 kernel/debug/kms_hooks.c

diff --git a/drivers/serial/kgdboc.c b/drivers/serial/kgdboc.c
index 93b18f9..05d1605 100644
--- a/drivers/serial/kgdboc.c
+++ b/drivers/serial/kgdboc.c
@@ -204,13 +204,19 @@ static int param_set_kgdboc_var(const char *kmessage, struct kernel_param *kp)
 	return configure_kgdboc();
 }
 
+static int dbg_restore_graphics;
+
 static void kgdboc_pre_exp_handler(void)
 {
-	if (kgdboc_use_kms && dbg_kms_console_core &&
-	    dbg_kms_console_core->activate_console)
-		if (dbg_kms_console_core->activate_console(dbg_kms_console_core))
+	if (!dbg_restore_graphics && kgdboc_use_kms && dbg_kms_console_core &&
+	    dbg_kms_console_core->activate_console) {
+		if (dbg_kms_console_core->activate_console(dbg_kms_console_core)) {
 			printk(KERN_ERR "kgdboc: kernel mode switch error\n");
-
+		} else {
+			dbg_restore_graphics = 1;
+			dbg_pre_vt_hook();
+		}
+	}
 	/* Increment the module count when the debugger is active */
 	if (!kgdb_connected)
 		try_module_get(THIS_MODULE);
@@ -222,9 +228,15 @@ static void kgdboc_post_exp_handler(void)
 	if (!kgdb_connected)
 		module_put(THIS_MODULE);
 	if (kgdboc_use_kms && dbg_kms_console_core &&
-	    dbg_kms_console_core->restore_console)
-		if (dbg_kms_console_core->restore_console(dbg_kms_console_core))
-			printk(KERN_ERR "kgdboc: graphics restore failed\n");
+	    dbg_kms_console_core->restore_console) {
+		if (dbg_restore_graphics) {
+			if (dbg_kms_console_core->restore_console(dbg_kms_console_core))
+				printk(KERN_ERR "kgdboc: graphics restore failed\n");
+			dbg_restore_graphics = 0;
+			dbg_post_vt_hook();
+		}
+	}
+
 #ifdef CONFIG_KDB_KEYBOARD
 	/* If using the kdb keyboard driver release all the keys. */
 	if (kgdboc_use_kbd)
diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c
index 3681c6a..6f2ed5a 100644
--- a/drivers/video/console/fbcon.c
+++ b/drivers/video/console/fbcon.c
@@ -75,6 +75,7 @@
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/crc32.h> /* For counting font checksums */
+#include <linux/kgdb.h>
 #include <asm/fb.h>
 #include <asm/irq.h>
 #include <asm/system.h>
@@ -2318,6 +2319,12 @@ static int fbcon_blank(struct vc_data *vc, int blank, int mode_switch)
 		}
 	}
 
+	if (in_dbg_master()) {
+		if (info->fbops->fb_blank)
+			info->fbops->fb_blank(blank, info);
+		return 0;
+	}
+
  	if (!fbcon_is_inactive(vc, info)) {
 		if (ops->blank_state != blank) {
 			ops->blank_state = blank;
diff --git a/include/linux/kgdb.h b/include/linux/kgdb.h
index 68fa243..df67f05 100644
--- a/include/linux/kgdb.h
+++ b/include/linux/kgdb.h
@@ -288,6 +288,14 @@ extern void __init early_kgdboc_init(void);
 #endif /* CONFIG_KGDB */
 
 /* Common to all that include kgdb.h */
+#ifdef CONFIG_VT
+extern void dbg_pre_vt_hook(void);
+extern void dbg_post_vt_hook(void);
+#else /* ! CONFIG_VT */
+#define dbg_pre_vt_hook()
+#define dbg_post_vt_hook()
+#endif /* CONFIG_VT */
+
 struct dbg_kms_console_ops {
 	int (*activate_console) (struct dbg_kms_console_ops *ops);
 	int (*restore_console) (struct dbg_kms_console_ops *ops);
@@ -297,6 +305,14 @@ struct dbg_kms_console_ops {
 extern struct dbg_kms_console_ops *dbg_kms_console_core;
 extern int dbg_kms_console_ops_register(struct dbg_kms_console_ops *ops);
 extern int dbg_kms_console_ops_unregister(struct dbg_kms_console_ops *ops);
+#define in_dbg_master() \
+	(raw_smp_processor_id() == atomic_read(&kgdb_active))
+#define dbg_safe_mutex_lock(x) \
+	if (!in_dbg_master()) \
+		mutex_lock(x)
+#define dbg_safe_mutex_unlock(x) \
+	if (!in_dbg_master()) \
+		mutex_unlock(x)
 #else /* ! CONFIG_KGDB */
 static inline int dbg_kms_console_ops_register(struct dbg_kms_console_ops *ops)
 {
@@ -306,5 +322,8 @@ static inline int dbg_kms_console_ops_unregister(struct dbg_kms_console_ops *ops
 {
        return 0;
 }
+#define in_dbg_master() (0)
+#define dbg_safe_mutex_lock(x) mutex_lock(x)
+#define dbg_safe_mutex_unlock(x) mutex_unlock(x)
 #endif /* ! CONFIG_KGDB */
 #endif /* _KGDB_H_ */
diff --git a/kernel/debug/Makefile b/kernel/debug/Makefile
index c72de00..fe342c0 100644
--- a/kernel/debug/Makefile
+++ b/kernel/debug/Makefile
@@ -3,5 +3,6 @@
 #
 
 obj-$(CONFIG_KGDB) += debug_core.o gdbstub.o
+obj-$(CONFIG_VT) += kms_hooks.o
 obj-$(CONFIG_KGDB_KDB) += kdb/
 
diff --git a/kernel/debug/debug_core.c b/kernel/debug/debug_core.c
index 82c7c47..6ca3f7c 100644
--- a/kernel/debug/debug_core.c
+++ b/kernel/debug/debug_core.c
@@ -106,6 +106,7 @@ static struct kgdb_bkpt		kgdb_break[KGDB_MAX_BREAKPOINTS] = {
  * The CPU# of the active CPU, or -1 if none:
  */
 atomic_t			kgdb_active = ATOMIC_INIT(-1);
+EXPORT_SYMBOL_GPL(kgdb_active);
 
 /*
  * We use NR_CPUs not PERCPU, in case kgdb is used to debug early
diff --git a/kernel/debug/kms_hooks.c b/kernel/debug/kms_hooks.c
new file mode 100644
index 0000000..c56b7ce
--- /dev/null
+++ b/kernel/debug/kms_hooks.c
@@ -0,0 +1,62 @@
+/*
+ * Created by: Jason Wessel <jason.wessel@...driver.com>
+ *
+ * Copyright (c) 2009 Wind River Systems, Inc.  All Rights Reserved.
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2. This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#ifdef CONFIG_VT
+#include <linux/kgdb.h>
+#include <linux/console.h>
+#include <linux/vt_kern.h>
+#include <linux/selection.h>
+#include <linux/kdb.h>
+#include "kdb/kdb_private.h"
+
+static int dbg_orig_vc_mode;
+static int saved_fg_con;
+static int saved_last_con;
+static int saved_want_con;
+
+void dbg_pre_vt_hook(void)
+{
+	struct vc_data *vc = vc_cons[fg_console].d;
+	saved_fg_con = fg_console;
+	saved_last_con = last_console;
+	saved_want_con = want_console;
+	dbg_orig_vc_mode = vc->vc_mode;
+	vc->vc_mode = KD_TEXT;
+	console_blanked = 0;
+	vc->vc_sw->con_blank(vc, 0, 1);
+	vc->vc_sw->con_set_palette(vc, color_table);
+#ifdef CONFIG_KGDB_KDB
+	/* Set the initial LINES variable if it is not already set */
+	if (vc->vc_rows < 999) {
+		int linecount;
+		char lns[4];
+		const char *setargs[3] = {
+			"set",
+			"LINES",
+			lns,
+		};
+		if (kdbgetintenv(setargs[0], &linecount)) {
+			snprintf(lns, 4, "%i", vc->vc_rows);
+			kdb_set(2, setargs);
+		}
+	}
+#endif /* CONFIG_KGDB_KDB */
+}
+EXPORT_SYMBOL_GPL(dbg_pre_vt_hook);
+
+void dbg_post_vt_hook(void)
+{
+	fg_console = saved_fg_con;
+	last_console = saved_last_con;
+	want_console = saved_want_con;
+	vc_cons[fg_console].d->vc_mode = dbg_orig_vc_mode;
+}
+EXPORT_SYMBOL_GPL(dbg_post_vt_hook);
+#endif /* CONFIG_VT */
-- 
1.6.3.1.9.g95405b

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