[PATCH] arch/x86_64/kernel/traps.c

From: John Blackwood
Date: Tue Dec 13 2005 - 11:31:48 EST


Hi Andi,

I would like to throw out a suggestion for a possible change in the way that
the debug register traps are handled in do_debug() when the trap occurs
in kernel-mode.

In the x86_64 version of do_debug(), the code will skip around sending
a SIGTRAP to the current task if the trap occurred while in kernel mode.

On the i386-side of things, if the access happens to occur in kernel mode
(say during a read(2) of user's buffer that matches the address of a
debug register trap), then the do_debug() routine for i386 will go ahead
and call send_sigtrap() and send the SIGTRAP signal. The send_sigtrap()
code will also set the info.si_addr to NULL in this case (even though I
don't understand why, since the SIGTRAP siginfo processing doesn't use
the si_addr field...).

So I would like to suggest that the x86_64 do_debug() routine also
follow this type of behavior and have it go ahead and send the
SIGTRAP signal to the current task, even if the debug register trap
happens to have occurred in kernel mode. I have taken a stab at
a patch for this change below. (It includes the i386-ish change
for setting si_addr to NULL when the trap occurred in kernel mode.)

It seems like a useful feature to be able to 'watch' a user location that
might also be modified in the kernel via a system service call, and have the
debugger report that information back to the user, rather than to just
silently ignore the trap.

Additionally, I realize that users that pull in a kernel debugger such as
KGDB into their kernel might want to remove this change below when they add
in KGDB support. However, they could alternatively look at the current
task's thread.debugreg[] values to see if the trap occurred due to KGDB
or instead because of a user-space debugger trap, and still honor the
user SIGTRAP processing (instead of the KGDB breakpoint processing)
if the trap matches up with the thread.debugreg[] registers.

Thank you for your time and consideration.



diff -up linux-2.6.14.3/arch/x86_64/kernel/traps.c new/arch/x86_64/kernel/traps.c
--- linux-2.6.14.3/arch/x86_64/kernel/traps.c 2005-11-24 17:10:21.000000000 -0500
+++ new/arch/x86_64/kernel/traps.c 2005-12-13 10:17:35.000000000 -0500
@@ -724,11 +724,9 @@ asmlinkage void __kprobes do_debug(struc
info.si_signo = SIGTRAP;
info.si_errno = 0;
info.si_code = TRAP_BRKPT;
- if (!user_mode(regs))
- goto clear_dr7;
-
- info.si_addr = (void __user *)regs->rip;
+ info.si_addr = user_mode(regs) ? (void __user *)regs->rip : NULL;
force_sig_info(SIGTRAP, &info, tsk);
+
clear_dr7:
set_debugreg(0UL, 7);
return;

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/