Skip to content

Commit

Permalink
kprobes: Remove kprobe::fault_handler
Browse files Browse the repository at this point in the history
The reason for kprobe::fault_handler(), as given by their comment:

 * 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.

Is just plain bad. Those other handlers are ran from non-preemptible
context and had better use _nofault() functions. Also, there is no
upstream usage of this.

Signed-off-by: Peter Zijlstra (Intel) <[email protected]>
Reviewed-by: Christoph Hellwig <[email protected]>
Acked-by: Masami Hiramatsu <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
  • Loading branch information
Peter Zijlstra committed Jun 1, 2021
1 parent 9ce4d21 commit ec6aba3
Show file tree
Hide file tree
Showing 16 changed files with 5 additions and 172 deletions.
24 changes: 5 additions & 19 deletions Documentation/trace/kprobes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -362,14 +362,11 @@ register_kprobe
#include <linux/kprobes.h>
int register_kprobe(struct kprobe *kp);

Sets a breakpoint at the address kp->addr. When the breakpoint is
hit, Kprobes calls kp->pre_handler. After the probed instruction
is single-stepped, Kprobe calls kp->post_handler. If a fault
occurs during execution of kp->pre_handler or kp->post_handler,
or during single-stepping of the probed instruction, Kprobes calls
kp->fault_handler. Any or all handlers can be NULL. If kp->flags
is set KPROBE_FLAG_DISABLED, that kp will be registered but disabled,
so, its handlers aren't hit until calling enable_kprobe(kp).
Sets a breakpoint at the address kp->addr. When the breakpoint is hit, Kprobes
calls kp->pre_handler. After the probed instruction is single-stepped, Kprobe
calls kp->post_handler. Any or all handlers can be NULL. If kp->flags is set
KPROBE_FLAG_DISABLED, that kp will be registered but disabled, so, its handlers
aren't hit until calling enable_kprobe(kp).

.. note::

Expand Down Expand Up @@ -415,17 +412,6 @@ User's post-handler (kp->post_handler)::
p and regs are as described for the pre_handler. flags always seems
to be zero.

User's fault-handler (kp->fault_handler)::

#include <linux/kprobes.h>
#include <linux/ptrace.h>
int fault_handler(struct kprobe *p, struct pt_regs *regs, int trapnr);

p and regs are as described for the pre_handler. trapnr is the
architecture-specific trap number associated with the fault (e.g.,
on i386, 13 for a general protection fault or 14 for a page fault).
Returns 1 if it successfully handled the exception.

register_kretprobe
------------------

Expand Down
10 changes: 0 additions & 10 deletions arch/arc/kernel/kprobes.c
Original file line number Diff line number Diff line change
Expand Up @@ -323,16 +323,6 @@ int __kprobes kprobe_fault_handler(struct pt_regs *regs, unsigned long trapnr)
*/
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;

/*
* In case the user-specified fault handler returned zero,
* try to fix up.
Expand Down
9 changes: 0 additions & 9 deletions arch/arm/probes/kprobes/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -358,15 +358,6 @@ int __kprobes kprobe_fault_handler(struct pt_regs *regs, unsigned int fsr)
*/
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.
*/
if (cur->fault_handler && cur->fault_handler(cur, regs, fsr))
return 1;
break;

default:
Expand Down
10 changes: 0 additions & 10 deletions arch/arm64/kernel/probes/kprobes.c
Original file line number Diff line number Diff line change
Expand Up @@ -283,16 +283,6 @@ int __kprobes kprobe_fault_handler(struct pt_regs *regs, unsigned int fsr)
*/
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, fsr))
return 1;

/*
* In case the user-specified fault handler returned
* zero, try to fix up.
Expand Down
10 changes: 0 additions & 10 deletions arch/csky/kernel/probes/kprobes.c
Original file line number Diff line number Diff line change
Expand Up @@ -301,16 +301,6 @@ int __kprobes kprobe_fault_handler(struct pt_regs *regs, unsigned int trapnr)
*/
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;

/*
* In case the user-specified fault handler returned
* zero, try to fix up.
Expand Down
9 changes: 0 additions & 9 deletions arch/ia64/kernel/kprobes.c
Original file line number Diff line number Diff line change
Expand Up @@ -850,15 +850,6 @@ int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr)
*/
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;
/*
* In case the user-specified fault handler returned
* zero, try to fix up.
Expand Down
3 changes: 0 additions & 3 deletions arch/mips/kernel/kprobes.c
Original file line number Diff line number Diff line change
Expand Up @@ -403,9 +403,6 @@ int kprobe_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, kcb);
regs->cp0_status |= kcb->kprobe_old_SR;
Expand Down
10 changes: 0 additions & 10 deletions arch/powerpc/kernel/kprobes.c
Original file line number Diff line number Diff line change
Expand Up @@ -508,16 +508,6 @@ int kprobe_fault_handler(struct pt_regs *regs, int trapnr)
*/
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;

/*
* In case the user-specified fault handler returned
* zero, try to fix up.
Expand Down
10 changes: 0 additions & 10 deletions arch/riscv/kernel/probes/kprobes.c
Original file line number Diff line number Diff line change
Expand Up @@ -283,16 +283,6 @@ int __kprobes kprobe_fault_handler(struct pt_regs *regs, unsigned int trapnr)
*/
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;

/*
* In case the user-specified fault handler returned
* zero, try to fix up.
Expand Down
10 changes: 0 additions & 10 deletions arch/s390/kernel/kprobes.c
Original file line number Diff line number Diff line change
Expand Up @@ -452,16 +452,6 @@ static int kprobe_trap_handler(struct pt_regs *regs, int trapnr)
*/
kprobes_inc_nmissed_count(p);

/*
* 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 (p->fault_handler && p->fault_handler(p, regs, trapnr))
return 1;

/*
* In case the user-specified fault handler returned
* zero, try to fix up.
Expand Down
10 changes: 0 additions & 10 deletions arch/sh/kernel/kprobes.c
Original file line number Diff line number Diff line change
Expand Up @@ -389,16 +389,6 @@ int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr)
*/
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;

/*
* In case the user-specified fault handler returned
* zero, try to fix up.
Expand Down
10 changes: 0 additions & 10 deletions arch/sparc/kernel/kprobes.c
Original file line number Diff line number Diff line change
Expand Up @@ -352,16 +352,6 @@ int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr)
*/
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;

/*
* In case the user-specified fault handler returned
* zero, try to fix up.
Expand Down
10 changes: 0 additions & 10 deletions arch/x86/kernel/kprobes/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -1110,16 +1110,6 @@ int kprobe_fault_handler(struct pt_regs *regs, int trapnr)
* 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;
}

return 0;
Expand Down
8 changes: 0 additions & 8 deletions include/linux/kprobes.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,6 @@ struct kretprobe_instance;
typedef int (*kprobe_pre_handler_t) (struct kprobe *, struct pt_regs *);
typedef void (*kprobe_post_handler_t) (struct kprobe *, struct pt_regs *,
unsigned long flags);
typedef int (*kprobe_fault_handler_t) (struct kprobe *, struct pt_regs *,
int trapnr);
typedef int (*kretprobe_handler_t) (struct kretprobe_instance *,
struct pt_regs *);

Expand Down Expand Up @@ -83,12 +81,6 @@ struct kprobe {
/* Called after addr is executed, unless... */
kprobe_post_handler_t post_handler;

/*
* ... called if executing addr causes a fault (eg. page fault).
* Return 1 if it handled fault, otherwise kernel will see it.
*/
kprobe_fault_handler_t fault_handler;

/* Saved opcode (which has been replaced with breakpoint) */
kprobe_opcode_t opcode;

Expand Down
19 changes: 0 additions & 19 deletions kernel/kprobes.c
Original file line number Diff line number Diff line change
Expand Up @@ -1183,23 +1183,6 @@ static void aggr_post_handler(struct kprobe *p, struct pt_regs *regs,
}
NOKPROBE_SYMBOL(aggr_post_handler);

static int aggr_fault_handler(struct kprobe *p, struct pt_regs *regs,
int trapnr)
{
struct kprobe *cur = __this_cpu_read(kprobe_instance);

/*
* if we faulted "during" the execution of a user specified
* probe handler, invoke just that probe's fault handler
*/
if (cur && cur->fault_handler) {
if (cur->fault_handler(cur, regs, trapnr))
return 1;
}
return 0;
}
NOKPROBE_SYMBOL(aggr_fault_handler);

/* Walks the list and increments nmissed count for multiprobe case */
void kprobes_inc_nmissed_count(struct kprobe *p)
{
Expand Down Expand Up @@ -1330,7 +1313,6 @@ static void init_aggr_kprobe(struct kprobe *ap, struct kprobe *p)
ap->addr = p->addr;
ap->flags = p->flags & ~KPROBE_FLAG_OPTIMIZED;
ap->pre_handler = aggr_pre_handler;
ap->fault_handler = aggr_fault_handler;
/* We don't care the kprobe which has gone. */
if (p->post_handler && !kprobe_gone(p))
ap->post_handler = aggr_post_handler;
Expand Down Expand Up @@ -2014,7 +1996,6 @@ int register_kretprobe(struct kretprobe *rp)

rp->kp.pre_handler = pre_handler_kretprobe;
rp->kp.post_handler = NULL;
rp->kp.fault_handler = NULL;

/* Pre-allocate memory for max kretprobe instances */
if (rp->maxactive <= 0) {
Expand Down
15 changes: 0 additions & 15 deletions samples/kprobes/kprobe_example.c
Original file line number Diff line number Diff line change
Expand Up @@ -94,26 +94,11 @@ static void __kprobes handler_post(struct kprobe *p, struct pt_regs *regs,
#endif
}

/*
* fault_handler: this is called if an exception is generated for any
* instruction within the pre- or post-handler, or when Kprobes
* single-steps the probed instruction.
*/
static int handler_fault(struct kprobe *p, struct pt_regs *regs, int trapnr)
{
pr_info("fault_handler: p->addr = 0x%p, trap #%dn", p->addr, trapnr);
/* Return 0 because we don't handle the fault. */
return 0;
}
/* NOKPROBE_SYMBOL() is also available */
NOKPROBE_SYMBOL(handler_fault);

static int __init kprobe_init(void)
{
int ret;
kp.pre_handler = handler_pre;
kp.post_handler = handler_post;
kp.fault_handler = handler_fault;

ret = register_kprobe(&kp);
if (ret < 0) {
Expand Down

0 comments on commit ec6aba3

Please sign in to comment.