Skip to content

Commit

Permalink
[PATCH] kprobes: fix broken fault handling for ia64
Browse files Browse the repository at this point in the history
Provide proper kprobes fault handling, if a user-specified pre/post handlers
tries to access user address space, through copy_from_user(), get_user() etc.

The user-specified fault handler gets called only if the fault occurs while
executing user-specified handlers.  In such a case user-specified handler is
allowed to fix it first, later if the user-specifed fault handler does not fix
it, we try to fix it by calling fix_exception().

The user-specified handler will not be called if the fault happens when single
stepping the original instruction, instead we reset the current probe and
allow the system page fault handler to fix it up.

Signed-off-by: Prasanna S Panchamukhi <prasanna@in.ibm.com>
Acked-by: Anil S Keshavamurthy<anil.s.keshavamurthy@intel.com>
Cc: "Luck, Tony" <tony.luck@intel.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
  • Loading branch information
Prasanna S Panchamukhi authored and Linus Torvalds committed Mar 26, 2006
1 parent 50e21f2 commit c04c1c8
Showing 1 changed file with 43 additions and 5 deletions.
48 changes: 43 additions & 5 deletions arch/ia64/kernel/kprobes.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
#include <asm/pgtable.h>
#include <asm/kdebug.h>
#include <asm/sections.h>
#include <asm/uaccess.h>

extern void jprobe_inst_return(void);

Expand Down Expand Up @@ -722,13 +723,50 @@ static int __kprobes kprobes_fault_handler(struct pt_regs *regs, int trapnr)
struct kprobe *cur = kprobe_running();
struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();

if (cur->fault_handler && cur->fault_handler(cur, regs, trapnr))
return 1;

if (kcb->kprobe_status & KPROBE_HIT_SS) {
resume_execution(cur, regs);
reset_current_kprobe();
switch(kcb->kprobe_status) {
case KPROBE_HIT_SS:
case KPROBE_REENTER:
/*
* We are here because the instruction being single
* stepped caused a page fault. We reset the current
* kprobe and the instruction pointer points back to
* the probe address and allow the page fault handler
* to continue as a normal page fault.
*/
regs->cr_iip = ((unsigned long)cur->addr) & ~0xFULL;
ia64_psr(regs)->ri = ((unsigned long)cur->addr) & 0xf;
if (kcb->kprobe_status == KPROBE_REENTER)
restore_previous_kprobe(kcb);
else
reset_current_kprobe();
preempt_enable_no_resched();
break;
case KPROBE_HIT_ACTIVE:
case KPROBE_HIT_SSDONE:
/*
* We increment the nmissed count for accounting,
* we can also use npre/npostfault count for accouting
* these specific fault cases.
*/
kprobes_inc_nmissed_count(cur);

/*
* We come here because instructions in the pre/post
* handler caused the page_fault, this could happen
* if handler tries to access user space by
* copy_from_user(), get_user() etc. Let the
* user-specified handler try to fix it first.
*/
if (cur->fault_handler && cur->fault_handler(cur, regs, trapnr))
return 1;

/*
* Let ia64_do_page_fault() fix it.
*/
break;
default:
break;
}

return 0;
Expand Down

0 comments on commit c04c1c8

Please sign in to comment.