If there are no objections, I'd like to apply this patch as it fixes a
critical gap when using source stepping that calls a low level
singlestep that steps the boundary from the kernel to the user space.
It is particularly bad when this corner case kills "init" as you get an
unexpected reboot.
---
This patch is to fix another corner case where kgdb can pass a single
step trap to user space which was intended for the kernel. Now a
source level "next" which single steps over an iret instruction will
cause KGDB to continue and print an error to the console, vs the
unpredictable consequence of sending a trap to unsuspecting code in
the user space (normally resulting in process termination).
Signed-off-by: Jason Wessel <[EMAIL PROTECTED]>
---
arch/i386/kernel/kgdb.c | 31 +++++++++++++++++++------------
arch/x86_64/kernel/kgdb.c | 17 ++++++++++++-----
2 files changed, 31 insertions(+), 17 deletions(-)
Index: linux-2.6.21-standard/arch/i386/kernel/kgdb.c
===================================================================
--- linux-2.6.21-standard.orig/arch/i386/kernel/kgdb.c
+++ linux-2.6.21-standard/arch/i386/kernel/kgdb.c
@@ -222,7 +222,7 @@ int kgdb_arch_handle_exception(int e_vec
if (remcom_in_buffer[0] == 's') {
linux_regs->eflags |= TF_MASK;
debugger_step = 1;
- atomic_set(&cpu_doing_single_step,smp_processor_id());
+ atomic_set(&cpu_doing_single_step,raw_smp_processor_id());
}
asm volatile ("movl %%db6, %0\n":"=r" (dr6));
@@ -255,22 +255,29 @@ static int kgdb_notify(struct notifier_b
/* Bad memory access? */
if (cmd == DIE_PAGE_FAULT_NO_CONTEXT && atomic_read(&debugger_active)
- && kgdb_may_fault) {
+ && kgdb_may_fault) {
kgdb_fault_longjmp(kgdb_fault_jmp_regs);
return NOTIFY_STOP;
} else if (cmd == DIE_PAGE_FAULT)
/* A normal page fault, ignore. */
return NOTIFY_DONE;
- else if ((cmd == DIE_NMI || cmd == DIE_NMI_IPI ||
- cmd == DIE_NMIWATCHDOG) && atomic_read(&debugger_active)) {
- /* CPU roundup */
- kgdb_nmihook(smp_processor_id(), regs);
- return NOTIFY_STOP;
- } else if (cmd == DIE_NMI_IPI || cmd == DIE_NMI ||
user_mode(regs) ||
- (cmd == DIE_DEBUG && atomic_read(&debugger_active)))
- /* Normal watchdog event or userspace debugging, or spurious
- * debug exception, ignore. */
- return NOTIFY_DONE;
+ else if ((cmd == DIE_NMI || cmd == DIE_NMI_IPI ||
+ cmd == DIE_NMIWATCHDOG) && atomic_read(&debugger_active)) {
+ /* CPU roundup */
+ kgdb_nmihook(raw_smp_processor_id(), regs);
+ return NOTIFY_STOP;
+ } else if (cmd == DIE_DEBUG && atomic_read(&cpu_doing_single_step)
!= -1
+ && user_mode(regs)) {
+ /* single step exception from kernel space to user space so
+ * eat the exception and continue the process
+ */
+ printk(KERN_ERR "KGDB: trap/step from kernel to user space,
resuming...\n");
+ return NOTIFY_STOP;
+ } else if (cmd == DIE_NMI_IPI || cmd == DIE_NMI || user_mode(regs) ||
+ (cmd == DIE_DEBUG && atomic_read(&debugger_active)))
+ /* Normal watchdog event or userspace debugging, or spurious
+ * debug exception, ignore. */
+ return NOTIFY_DONE;
kgdb_handle_exception(args->trapnr, args->signr, args->err, regs);
Index: linux-2.6.21-standard/arch/x86_64/kernel/kgdb.c
===================================================================
--- linux-2.6.21-standard.orig/arch/x86_64/kernel/kgdb.c
+++ linux-2.6.21-standard/arch/x86_64/kernel/kgdb.c
@@ -183,7 +183,7 @@ int kgdb_arch_handle_exception(int e_vec
debugger_step = 1;
if (kgdb_contthread)
atomic_set(&cpu_doing_single_step,
- smp_processor_id());
+ raw_smp_processor_id());
}
@@ -237,7 +237,7 @@ void kgdb_shadowinfo(struct pt_regs *reg
static char intr_desc[] = "Stack at interrupt entrypoint";
static char exc_desc[] = "Stack at exception entrypoint";
struct pt_regs *stregs;
- int cpu = smp_processor_id();
+ int cpu = raw_smp_processor_id();
if ((stregs = in_interrupt_stack(regs->rsp, cpu)))
kgdb_mem2hex(intr_desc, buffer, strlen(intr_desc));
@@ -248,7 +248,7 @@ void kgdb_shadowinfo(struct pt_regs *reg
struct task_struct *kgdb_get_shadow_thread(struct pt_regs *regs, int
threadid)
{
struct pt_regs *stregs;
- int cpu = smp_processor_id();
+ int cpu = raw_smp_processor_id();
if ((stregs = in_interrupt_stack(regs->rsp, cpu)))
return current;
@@ -261,7 +261,7 @@ struct task_struct *kgdb_get_shadow_thre
struct pt_regs *kgdb_shadow_regs(struct pt_regs *regs, int threadid)
{
struct pt_regs *stregs;
- int cpu = smp_processor_id();
+ int cpu = raw_smp_processor_id();
if ((stregs = in_interrupt_stack(regs->rsp, cpu)))
return stregs;
@@ -285,9 +285,16 @@ static int kgdb_notify(struct notifier_b
return NOTIFY_STOP;
/* CPU roundup? */
} else if (atomic_read(&debugger_active) && cmd == DIE_NMI_IPI) {
- kgdb_nmihook(smp_processor_id(), regs);
+ kgdb_nmihook(raw_smp_processor_id(), regs);
return NOTIFY_STOP;
/* See if KGDB is interested. */
+ } else if (cmd == DIE_DEBUG && atomic_read(&cpu_doing_single_step)
!= -1
+ && user_mode(regs)) {
+ /* single step exception from kernel space to user space so
+ * eat the exception and continue the process
+ */
+ printk(KERN_ERR "KGDB: trap/step from kernel to user space,
resuming...\n");
+ return NOTIFY_STOP;
} else if (cmd == DIE_PAGE_FAULT || user_mode(regs) ||
cmd == DIE_NMI_IPI || (cmd == DIE_DEBUG &&
atomic_read(&debugger_active)))
-------------------------------------------------------------------------
This SF.net email is sponsored by DB2 Express
Download DB2 Express C - the FREE version of DB2 express and take
control of your XML. No limits. Just data. Click to get it now.
http://sourceforge.net/powerbar/db2/
_______________________________________________
Kgdb-bugreport mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/kgdb-bugreport