aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/kprobes.c
diff options
context:
space:
mode:
authorAbhishek Sagar <sagar.abhishek@gmail.com>2008-01-30 07:33:13 -0500
committerIngo Molnar <mingo@elte.hu>2008-01-30 07:33:13 -0500
commitfb8830e72d9bd86f1e7b6886cb1886c391130f86 (patch)
tree1be87ec5258d9b6cf3ab877c3b3e723db8f98aad /arch/x86/kernel/kprobes.c
parent0723a69a63beec1ca6e792239ef75d0181387ef0 (diff)
x86: fix singlestep handling in reenter_kprobe
Highlight peculiar cases in singles-step kprobe handling. In reenter_kprobe(), a breakpoint in KPROBE_HIT_SS case can only occur when single-stepping a breakpoint on which a probe was installed. Since such probes are single-stepped inline, identifying these cases is unambiguous. All other cases leading up to KPROBE_HIT_SS are possible bugs. Identify and WARN_ON such cases. Signed-off-by: Abhishek Sagar <sagar.abhishek@gmail.com> Signed-off-by: Ingo Molnar <mingo@elte.hu> Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'arch/x86/kernel/kprobes.c')
-rw-r--r--arch/x86/kernel/kprobes.c28
1 files changed, 13 insertions, 15 deletions
diff --git a/arch/x86/kernel/kprobes.c b/arch/x86/kernel/kprobes.c
index edc0a8e59247..f7ddbb8c3fe8 100644
--- a/arch/x86/kernel/kprobes.c
+++ b/arch/x86/kernel/kprobes.c
@@ -443,17 +443,6 @@ void __kprobes arch_prepare_kretprobe(struct kretprobe_instance *ri,
443 *sara = (unsigned long) &kretprobe_trampoline; 443 *sara = (unsigned long) &kretprobe_trampoline;
444} 444}
445 445
446static void __kprobes recursive_singlestep(struct kprobe *p,
447 struct pt_regs *regs,
448 struct kprobe_ctlblk *kcb)
449{
450 save_previous_kprobe(kcb);
451 set_current_kprobe(p, regs, kcb);
452 kprobes_inc_nmissed_count(p);
453 prepare_singlestep(p, regs);
454 kcb->kprobe_status = KPROBE_REENTER;
455}
456
457static void __kprobes setup_singlestep(struct kprobe *p, struct pt_regs *regs, 446static void __kprobes setup_singlestep(struct kprobe *p, struct pt_regs *regs,
458 struct kprobe_ctlblk *kcb) 447 struct kprobe_ctlblk *kcb)
459{ 448{
@@ -492,20 +481,29 @@ static int __kprobes reenter_kprobe(struct kprobe *p, struct pt_regs *regs,
492 break; 481 break;
493#endif 482#endif
494 case KPROBE_HIT_ACTIVE: 483 case KPROBE_HIT_ACTIVE:
495 recursive_singlestep(p, regs, kcb); 484 save_previous_kprobe(kcb);
485 set_current_kprobe(p, regs, kcb);
486 kprobes_inc_nmissed_count(p);
487 prepare_singlestep(p, regs);
488 kcb->kprobe_status = KPROBE_REENTER;
496 break; 489 break;
497 case KPROBE_HIT_SS: 490 case KPROBE_HIT_SS:
498 if (*p->ainsn.insn == BREAKPOINT_INSTRUCTION) { 491 if (p == kprobe_running()) {
499 regs->flags &= ~TF_MASK; 492 regs->flags &= ~TF_MASK;
500 regs->flags |= kcb->kprobe_saved_flags; 493 regs->flags |= kcb->kprobe_saved_flags;
501 return 0; 494 return 0;
502 } else { 495 } else {
503 recursive_singlestep(p, regs, kcb); 496 /* A probe has been hit in the codepath leading up
497 * to, or just after, single-stepping of a probed
498 * instruction. This entire codepath should strictly
499 * reside in .kprobes.text section. Raise a warning
500 * to highlight this peculiar case.
501 */
504 } 502 }
505 break;
506 default: 503 default:
507 /* impossible cases */ 504 /* impossible cases */
508 WARN_ON(1); 505 WARN_ON(1);
506 return 0;
509 } 507 }
510 508
511 return 1; 509 return 1;