aboutsummaryrefslogtreecommitdiffstats
path: root/arch/i386/kernel/kprobes.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/i386/kernel/kprobes.c')
-rw-r--r--arch/i386/kernel/kprobes.c57
1 files changed, 50 insertions, 7 deletions
diff --git a/arch/i386/kernel/kprobes.c b/arch/i386/kernel/kprobes.c
index df1b346d36ff..f19768789e8a 100644
--- a/arch/i386/kernel/kprobes.c
+++ b/arch/i386/kernel/kprobes.c
@@ -35,6 +35,7 @@
35#include <asm/cacheflush.h> 35#include <asm/cacheflush.h>
36#include <asm/kdebug.h> 36#include <asm/kdebug.h>
37#include <asm/desc.h> 37#include <asm/desc.h>
38#include <asm/uaccess.h>
38 39
39void jprobe_return_end(void); 40void jprobe_return_end(void);
40 41
@@ -547,15 +548,57 @@ static inline int kprobe_fault_handler(struct pt_regs *regs, int trapnr)
547 struct kprobe *cur = kprobe_running(); 548 struct kprobe *cur = kprobe_running();
548 struct kprobe_ctlblk *kcb = get_kprobe_ctlblk(); 549 struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
549 550
550 if (cur->fault_handler && cur->fault_handler(cur, regs, trapnr)) 551 switch(kcb->kprobe_status) {
551 return 1; 552 case KPROBE_HIT_SS:
552 553 case KPROBE_REENTER:
553 if (kcb->kprobe_status & KPROBE_HIT_SS) { 554 /*
554 resume_execution(cur, regs, kcb); 555 * We are here because the instruction being single
556 * stepped caused a page fault. We reset the current
557 * kprobe and the eip points back to the probe address
558 * and allow the page fault handler to continue as a
559 * normal page fault.
560 */
561 regs->eip = (unsigned long)cur->addr;
555 regs->eflags |= kcb->kprobe_old_eflags; 562 regs->eflags |= kcb->kprobe_old_eflags;
556 563 if (kcb->kprobe_status == KPROBE_REENTER)
557 reset_current_kprobe(); 564 restore_previous_kprobe(kcb);
565 else
566 reset_current_kprobe();
558 preempt_enable_no_resched(); 567 preempt_enable_no_resched();
568 break;
569 case KPROBE_HIT_ACTIVE:
570 case KPROBE_HIT_SSDONE:
571 /*
572 * We increment the nmissed count for accounting,
573 * we can also use npre/npostfault count for accouting
574 * these specific fault cases.
575 */
576 kprobes_inc_nmissed_count(cur);
577
578 /*
579 * We come here because instructions in the pre/post
580 * handler caused the page_fault, this could happen
581 * if handler tries to access user space by
582 * copy_from_user(), get_user() etc. Let the
583 * user-specified handler try to fix it first.
584 */
585 if (cur->fault_handler && cur->fault_handler(cur, regs, trapnr))
586 return 1;
587
588 /*
589 * In case the user-specified fault handler returned
590 * zero, try to fix up.
591 */
592 if (fixup_exception(regs))
593 return 1;
594
595 /*
596 * fixup_exception() could not handle it,
597 * Let do_page_fault() fix it.
598 */
599 break;
600 default:
601 break;
559 } 602 }
560 return 0; 603 return 0;
561} 604}