From: tip-bot for Masami Hiramatsu on
Commit-ID: 51a66680aa450c81a1f31570700b6ade4886c841
Gitweb: http://git.kernel.org/tip/51a66680aa450c81a1f31570700b6ade4886c841
Author: Masami Hiramatsu <mhiramat(a)redhat.com>
AuthorDate: Tue, 27 Apr 2010 18:33:49 -0400
Committer: Ingo Molnar <mingo(a)elte.hu>
CommitDate: Sat, 8 May 2010 13:19:29 +0200

kprobes/x86: Fix removed int3 checking order

Fix kprobe/x86 to check removed int3 when failing to get kprobe
from hlist. Since we have a time window between checking int3
exists on probed address and getting kprobe on that address,
we can have following scenario:

-------
CPU1 CPU2
hit int3
check int3 exists
remove int3
remove kprobe from hlist
get kprobe from hlist
no kprobe->OOPS!
-------

This patch moves int3 checking if there is no kprobe on that
address for fixing this problem as follows:

------
CPU1 CPU2
hit int3
remove int3
remove kprobe from hlist
get kprobe from hlist
no kprobe->check int3 exists
->rollback&retry
------

Signed-off-by: Masami Hiramatsu <mhiramat(a)redhat.com>
Acked-by: Ananth N Mavinakayanahalli <ananth(a)in.ibm.com>
Cc: systemtap <systemtap(a)sources.redhat.com>
Cc: DLE <dle-develop(a)lists.sourceforge.net>
Cc: Dave Anderson <anderson(a)redhat.com>
Cc: Peter Zijlstra <a.p.zijlstra(a)chello.nl>
Cc: Mike Galbraith <efault(a)gmx.de>
Cc: Paul Mackerras <paulus(a)samba.org>
Cc: Arnaldo Carvalho de Melo <acme(a)redhat.com>
Cc: Frederic Weisbecker <fweisbec(a)gmail.com>
LKML-Reference: <20100427223348.2322.9112.stgit(a)localhost6.localdomain6>
Signed-off-by: Ingo Molnar <mingo(a)elte.hu>
---
arch/x86/kernel/kprobes.c | 27 +++++++++++++--------------
1 files changed, 13 insertions(+), 14 deletions(-)

diff --git a/arch/x86/kernel/kprobes.c b/arch/x86/kernel/kprobes.c
index b43bbae..1658efd 100644
--- a/arch/x86/kernel/kprobes.c
+++ b/arch/x86/kernel/kprobes.c
@@ -534,20 +534,6 @@ static int __kprobes kprobe_handler(struct pt_regs *regs)
struct kprobe_ctlblk *kcb;

addr = (kprobe_opcode_t *)(regs->ip - sizeof(kprobe_opcode_t));
- if (*addr != BREAKPOINT_INSTRUCTION) {
- /*
- * The breakpoint instruction was removed right
- * after we hit it. Another cpu has removed
- * either a probepoint or a debugger breakpoint
- * at this address. In either case, no further
- * handling of this interrupt is appropriate.
- * Back up over the (now missing) int3 and run
- * the original instruction.
- */
- regs->ip = (unsigned long)addr;
- return 1;
- }
-
/*
* We don't want to be preempted for the entire
* duration of kprobe processing. We conditionally
@@ -579,6 +565,19 @@ static int __kprobes kprobe_handler(struct pt_regs *regs)
setup_singlestep(p, regs, kcb, 0);
return 1;
}
+ } else if (*addr != BREAKPOINT_INSTRUCTION) {
+ /*
+ * The breakpoint instruction was removed right
+ * after we hit it. Another cpu has removed
+ * either a probepoint or a debugger breakpoint
+ * at this address. In either case, no further
+ * handling of this interrupt is appropriate.
+ * Back up over the (now missing) int3 and run
+ * the original instruction.
+ */
+ regs->ip = (unsigned long)addr;
+ preempt_enable_no_resched();
+ return 1;
} else if (kprobe_running()) {
p = __get_cpu_var(current_kprobe);
if (p->break_handler && p->break_handler(p, regs)) {
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo(a)vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/