From 01b8faaef5d239aeabb1e712c5d9619f29e808dd Mon Sep 17 00:00:00 2001 From: John Blackwood Date: Wed, 11 Jan 2006 22:44:15 +0100 Subject: [PATCH] x86_64: Report hardware breakpoints in user space when triggered by the kernel 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. Signed-off-by: Andi Kleen Signed-off-by: Linus Torvalds --- arch/x86_64/kernel/traps.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'arch/x86_64') diff --git a/arch/x86_64/kernel/traps.c b/arch/x86_64/kernel/traps.c index 1a9094d..8d21d87 100644 --- a/arch/x86_64/kernel/traps.c +++ b/arch/x86_64/kernel/traps.c @@ -726,11 +726,9 @@ asmlinkage void __kprobes do_debug(struct pt_regs * regs, info.si_signo = SIGTRAP; info.si_errno = 0; info.si_code = TRAP_BRKPT; - if (!user_mode(regs)) - goto clear_dr7; + info.si_addr = user_mode(regs) ? (void __user *)regs->rip : NULL; + force_sig_info(SIGTRAP, &info, tsk); - info.si_addr = (void __user *)regs->rip; - force_sig_info(SIGTRAP, &info, tsk); clear_dr7: set_debugreg(0UL, 7); return; -- cgit v1.1