Skip to content

Commit

Permalink
[PATCH] Kprobes/IA64: fix race when break hits and kprobe not found
Browse files Browse the repository at this point in the history
This patch addresses a potential race condition for a case where Kprobe has
been removed right after another CPU has taken a break hit.

The way this is addressed here is when the CPU that has taken a break hit
does not find its corresponding kprobe, then we check to see if the
original instruction got replaced with other than break.  If it got
replaced with other than break instruction, then we continue to execute
from the replaced instruction, else if we find that it is still a break,
then we let the kernel handle this, as this might be the break instruction
inserted by other than kprobe(may be kernel debugger).

Signed-off-by: Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
  • Loading branch information
Keshavamurthy Anil S authored and Linus Torvalds committed Sep 7, 2005
1 parent 8300516 commit 661e5a3
Showing 1 changed file with 45 additions and 0 deletions.
45 changes: 45 additions & 0 deletions arch/ia64/kernel/kprobes.c
Original file line number Diff line number Diff line change
Expand Up @@ -554,6 +554,38 @@ static void __kprobes prepare_ss(struct kprobe *p, struct pt_regs *regs)
ia64_psr(regs)->ss = 1;
}

static int __kprobes is_ia64_break_inst(struct pt_regs *regs)
{
unsigned int slot = ia64_psr(regs)->ri;
unsigned int template, major_opcode;
unsigned long kprobe_inst;
unsigned long *kprobe_addr = (unsigned long *)regs->cr_iip;
bundle_t bundle;

memcpy(&bundle, kprobe_addr, sizeof(bundle_t));
template = bundle.quad0.template;

/* Move to slot 2, if bundle is MLX type and kprobe slot is 1 */
if (slot == 1 && bundle_encoding[template][1] == L)
slot++;

/* Get Kprobe probe instruction at given slot*/
get_kprobe_inst(&bundle, slot, &kprobe_inst, &major_opcode);

/* For break instruction,
* Bits 37:40 Major opcode to be zero
* Bits 27:32 X6 to be zero
* Bits 32:35 X3 to be zero
*/
if (major_opcode || ((kprobe_inst >> 27) & 0x1FF) ) {
/* Not a break instruction */
return 0;
}

/* Is a break instruction */
return 1;
}

static int __kprobes pre_kprobes_handler(struct die_args *args)
{
struct kprobe *p;
Expand Down Expand Up @@ -601,6 +633,19 @@ static int __kprobes pre_kprobes_handler(struct die_args *args)
p = get_kprobe(addr);
if (!p) {
unlock_kprobes();
if (!is_ia64_break_inst(regs)) {
/*
* 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.
*/
ret = 1;

}

/* Not one of our break, let kernel handle it */
goto no_kprobe;
}

Expand Down

0 comments on commit 661e5a3

Please sign in to comment.