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]
Message-ID: <479FBA3B.5050209@web.de>
Date:	Wed, 30 Jan 2008 00:43:55 +0100
From:	Jan Kiszka <jan.kiszka@....de>
To:	Jason Wessel <jason.wessel@...driver.com>
CC:	Ingo Molnar <mingo@...e.hu>,
	Linux Kernel Mailing List <linux-kernel@...r.kernel.org>,
	kgdb-bugreport@...ts.sourceforge.net
Subject: [PATCH 1/5] KGDB: improve early init

[Warning in advance]
This patch reintroduces the early KGDB_CONSOLE registration issue: If
you switch this on, trigger the debugger before any tty-providing
console was registered and you do not provide an explicit console=
parameter, you end up with a panic due to lacking /dev/console. But this
time I have a better fix (for register_console), will be posted
separately later on.

<--snip-->

In case "kgdbwait" is passed as kernel parameter, KGDB tries to set up
and connect to the front-end already during early_param evaluation. This
fails on x86 as the exception stack is not yet initialized, effectively
delaying kgdbwait until late-init.

Therefore, this patch hooks into the x86 trap initialization and
re-triggers the KGDB setup, including a potential early rendezvous with
gdb. As a precondition, KGDB's setup states are refactored once again to
allow multiple invocations of kgdb_early_entry and correct tracking of
pending kgdbwait requests.

Signed-off-by: Jan Kiszka <jan.kiszka@....de>

---
 arch/x86/kernel/traps_32.c |    4 +++
 arch/x86/kernel/traps_64.c |    4 +++
 include/linux/kgdb.h       |    7 ++++-
 kernel/kgdb.c              |   55 ++++++++++++++++++++++++---------------------
 4 files changed, 44 insertions(+), 26 deletions(-)

Index: b/arch/x86/kernel/traps_32.c
===================================================================
--- a/arch/x86/kernel/traps_32.c
+++ b/arch/x86/kernel/traps_32.c
@@ -25,6 +25,7 @@
 #include <linux/utsname.h>
 #include <linux/kprobes.h>
 #include <linux/kexec.h>
+#include <linux/kgdb.h>
 #include <linux/unwind.h>
 #include <linux/uaccess.h>
 #include <linux/nmi.h>
@@ -1215,6 +1216,9 @@ void __init trap_init(void)
 	 */
 	cpu_init();
 
+	/* With the TSS set up, it's now save to arm early KGDB. */
+	kgdb_early_entry();
+
 	trap_init_hook();
 }
 
Index: b/arch/x86/kernel/traps_64.c
===================================================================
--- a/arch/x86/kernel/traps_64.c
+++ b/arch/x86/kernel/traps_64.c
@@ -27,6 +27,7 @@
 #include <linux/nmi.h>
 #include <linux/kprobes.h>
 #include <linux/kexec.h>
+#include <linux/kgdb.h>
 #include <linux/unwind.h>
 #include <linux/uaccess.h>
 #include <linux/bug.h>
@@ -1162,6 +1163,9 @@ void __init trap_init(void)
 	 * Should be a barrier for any external CPU state.
 	 */
 	cpu_init();
+
+	/* With the TSS set up, it's now save to arm early KGDB. */
+	kgdb_early_entry();
 }
 
 
Index: b/include/linux/kgdb.h
===================================================================
--- a/include/linux/kgdb.h
+++ b/include/linux/kgdb.h
@@ -46,7 +46,8 @@ extern struct task_struct *kgdb_usethrea
 
 enum kgdb_initstate {
 	KGDB_UNINITIALIZED = 0,
-	KGDB_SEMI_INITIALIZED,
+	KGDB_ARCH_INITIALIZED,
+	KGDB_DELAYED_CONNECTION,
 	KGDB_FULLY_INITIALIZED
 };
 
@@ -286,11 +287,15 @@ int kgdb_handle_exception(int ex_vector,
 			  struct pt_regs *regs);
 int kgdb_nmihook(int cpu, void *regs);
 
+void __init kgdb_early_entry(void);
+
 extern int debugger_step;
 extern atomic_t debugger_active;
 
 #else /* !CONFIG_KGDB */
 static const atomic_t debugger_active = ATOMIC_INIT(0);
+
+static inline void kgdb_early_entry(void) { }
 #endif /* !CONFIG_KGDB */
 
 #endif /* _KGDB_H_ */
Index: b/kernel/kgdb.c
===================================================================
--- a/kernel/kgdb.c
+++ b/kernel/kgdb.c
@@ -1925,32 +1925,39 @@ void kgdb_unregister_io_module(struct kg
 }
 EXPORT_SYMBOL_GPL(kgdb_unregister_io_module);
 
+static void __init kgdb_initial_breakpoint(void)
+{
+	printk(KERN_CRIT "kgdb: Waiting for connection from remote gdb...\n");
+	breakpoint();
+}
+
 /*
  * This function can be called very early, either via early_param() or
  * an explicit breakpoint() early on.
  */
-static void __init kgdb_early_entry(void)
+void __init kgdb_early_entry(void)
 {
+	int need_break = (kgdb_state == KGDB_DELAYED_CONNECTION);
+
 	/* Let the architecture do any setup that it needs to. */
-	kgdb_arch_init();
+	if (kgdb_state == KGDB_UNINITIALIZED) {
+		kgdb_arch_init();
+		kgdb_state = KGDB_ARCH_INITIALIZED;
+	}
 
 	/*
 	 * Don't try and do anything until the architecture is able to
 	 * setup the exception stack.  In this case, it is up to the
 	 * architecture to hook in and look at us when they are ready.
 	 */
-
-	if (!EXCEPTION_STACK_READY()) {
-		kgdb_state = KGDB_SEMI_INITIALIZED;
-		/* any kind of break point is deferred to late_init */
+	if (!EXCEPTION_STACK_READY())
 		return;
-	}
 
 	/* Now try the I/O. */
 	/* For early entry kgdb_io_ops.init must be defined */
 	if (!kgdb_io_ops.init || kgdb_io_ops.init()) {
-		/* Try again later. */
-		kgdb_state = KGDB_SEMI_INITIALIZED;
+		printk(KERN_ERR "kgdb: Could not setup core I/O for KGDB.\n");
+		printk(KERN_INFO "kgdb: Defering I/O setup to late init.\n");
 		return;
 	}
 
@@ -1964,6 +1971,9 @@ static void __init kgdb_early_entry(void
 	 */
 	if (kgdb_io_ops.init)
 		kgdb_register_for_panic();
+
+	if (need_break)
+		kgdb_initial_breakpoint();
 }
 
 /*
@@ -1974,14 +1984,16 @@ static void __init kgdb_early_entry(void
  */
 static int __init kgdb_late_entry(void)
 {
-	int need_break = (kgdb_state == KGDB_SEMI_INITIALIZED);
+	int need_break = (kgdb_state == KGDB_DELAYED_CONNECTION);
 
 	/*
 	 * If we haven't tried to initialize KGDB yet, we need to call
 	 * kgdb_arch_init before moving onto the I/O.
 	 */
-	if (kgdb_state == KGDB_UNINITIALIZED)
+	if (kgdb_state == KGDB_UNINITIALIZED) {
 		kgdb_arch_init();
+		kgdb_state = KGDB_ARCH_INITIALIZED;
+	}
 
 	if (kgdb_state != KGDB_FULLY_INITIALIZED) {
 		if (kgdb_io_ops.init && kgdb_io_ops.init()) {
@@ -2015,11 +2027,8 @@ static int __init kgdb_late_entry(void)
 	if (kgdb_io_ops.late_init)
 		kgdb_io_ops.late_init();
 
-	if (need_break) {
-		printk(KERN_CRIT "kgdb: Waiting for connection from remote"
-		       " gdb...\n");
-		breakpoint();
-	}
+	if (need_break)
+		kgdb_initial_breakpoint();
 
 	return 0;
 }
@@ -2072,7 +2081,6 @@ module_init(gdb_register_sysrq);
 static int kgdb_notify_reboot(struct notifier_block *this,
 		unsigned long code, void *x)
 {
-
 	unsigned long flags;
 
 	/* If we're debugging, or KGDB has not connected, don't try
@@ -2093,6 +2101,7 @@ static int __init opt_kgdb_attachwait(ch
 	attachwait = 1;
 	return 0;
 }
+
 static int __init opt_kgdb_enter(char *str)
 {
 	/* We've already done this by an explicit breakpoint() call. */
@@ -2101,15 +2110,11 @@ static int __init opt_kgdb_enter(char *s
 
 	kgdb_early_entry();
 	attachwait = 1;
-	if (kgdb_state == KGDB_FULLY_INITIALIZED)
-		printk(KERN_CRIT "Waiting for connection from remote "
-		       "gdb...\n");
-	else {
-		printk(KERN_CRIT "KGDB cannot initialize I/O yet.\n");
-		return 0;
-	}
 
-	breakpoint();
+	if (kgdb_state == KGDB_FULLY_INITIALIZED)
+		kgdb_initial_breakpoint();
+	else
+		kgdb_state = KGDB_DELAYED_CONNECTION;
 
 	return 0;
 }
--
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