Skip to content

Commit

Permalink
[PATCH] Notify page fault call chain
Browse files Browse the repository at this point in the history
With this patch Kprobes now registers for page fault notifications only when
their is an active probe registered.  Once all the active probes are
unregistered their is no need to be notified of page faults and kprobes
unregisters itself from the page fault notifications.  Hence we will have ZERO
side effects when no probes are active.

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
Anil S Keshavamurthy authored and Linus Torvalds committed Jun 26, 2006
1 parent 3d5631e commit e6f47f9
Show file tree
Hide file tree
Showing 6 changed files with 29 additions and 7 deletions.
1 change: 1 addition & 0 deletions include/asm-i386/kprobes.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ typedef u8 kprobe_opcode_t;

#define JPROBE_ENTRY(pentry) (kprobe_opcode_t *)pentry
#define ARCH_SUPPORTS_KRETPROBES
#define ARCH_INACTIVE_KPROBE_COUNT 0

void arch_remove_kprobe(struct kprobe *p);
void kretprobe_trampoline(void);
Expand Down
1 change: 1 addition & 0 deletions include/asm-ia64/kprobes.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ struct kprobe_ctlblk {
#define JPROBE_ENTRY(pentry) (kprobe_opcode_t *)pentry

#define ARCH_SUPPORTS_KRETPROBES
#define ARCH_INACTIVE_KPROBE_COUNT 1

#define SLOT0_OPCODE_SHIFT (37)
#define SLOT1_p1_OPCODE_SHIFT (37 - (64-46))
Expand Down
2 changes: 2 additions & 0 deletions include/asm-powerpc/kprobes.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ typedef unsigned int kprobe_opcode_t;
IS_TWI(instr) || IS_TDI(instr))

#define ARCH_SUPPORTS_KRETPROBES
#define ARCH_INACTIVE_KPROBE_COUNT 1

void kretprobe_trampoline(void);
extern void arch_remove_kprobe(struct kprobe *p);

Expand Down
1 change: 1 addition & 0 deletions include/asm-sparc64/kprobes.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ typedef u32 kprobe_opcode_t;

#define JPROBE_ENTRY(pentry) (kprobe_opcode_t *)pentry
#define arch_remove_kprobe(p) do {} while (0)
#define ARCH_INACTIVE_KPROBE_COUNT 0

/* Architecture specific copy of original instruction*/
struct arch_specific_insn {
Expand Down
1 change: 1 addition & 0 deletions include/asm-x86_64/kprobes.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ typedef u8 kprobe_opcode_t;

#define JPROBE_ENTRY(pentry) (kprobe_opcode_t *)pentry
#define ARCH_SUPPORTS_KRETPROBES
#define ARCH_INACTIVE_KPROBE_COUNT 1

void kretprobe_trampoline(void);
extern void arch_remove_kprobe(struct kprobe *p);
Expand Down
30 changes: 23 additions & 7 deletions kernel/kprobes.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,17 @@

static struct hlist_head kprobe_table[KPROBE_TABLE_SIZE];
static struct hlist_head kretprobe_inst_table[KPROBE_TABLE_SIZE];
static atomic_t kprobe_count;

DEFINE_MUTEX(kprobe_mutex); /* Protects kprobe_table */
DEFINE_SPINLOCK(kretprobe_lock); /* Protects kretprobe_inst_table */
static DEFINE_PER_CPU(struct kprobe *, kprobe_instance) = NULL;

static struct notifier_block kprobe_page_fault_nb = {
.notifier_call = kprobe_exceptions_notify,
.priority = 0x7fffffff /* we need to notified first */
};

#ifdef __ARCH_WANT_KPROBES_INSN_SLOT
/*
* kprobe->ainsn.insn points to the copy of the instruction to be
Expand Down Expand Up @@ -465,6 +471,8 @@ static int __kprobes __register_kprobe(struct kprobe *p,
old_p = get_kprobe(p->addr);
if (old_p) {
ret = register_aggr_kprobe(old_p, p);
if (!ret)
atomic_inc(&kprobe_count);
goto out;
}

Expand All @@ -475,6 +483,10 @@ static int __kprobes __register_kprobe(struct kprobe *p,
hlist_add_head_rcu(&p->hlist,
&kprobe_table[hash_ptr(p->addr, KPROBE_HASH_BITS)]);

if (atomic_add_return(1, &kprobe_count) == \
(ARCH_INACTIVE_KPROBE_COUNT + 1))
register_page_fault_notifier(&kprobe_page_fault_nb);

arch_arm_kprobe(p);

out:
Expand Down Expand Up @@ -553,17 +565,23 @@ void __kprobes unregister_kprobe(struct kprobe *p)
}
mutex_unlock(&kprobe_mutex);
}

/* Call unregister_page_fault_notifier()
* if no probes are active
*/
mutex_lock(&kprobe_mutex);
if (atomic_add_return(-1, &kprobe_count) == \
ARCH_INACTIVE_KPROBE_COUNT)
unregister_page_fault_notifier(&kprobe_page_fault_nb);
mutex_unlock(&kprobe_mutex);
return;
}

static struct notifier_block kprobe_exceptions_nb = {
.notifier_call = kprobe_exceptions_notify,
.priority = 0x7fffffff /* we need to be notified first */
};

static struct notifier_block kprobe_page_fault_nb = {
.notifier_call = kprobe_exceptions_notify,
.priority = 0x7fffffff /* we need to notified first */
};

int __kprobes register_jprobe(struct jprobe *jp)
{
Expand Down Expand Up @@ -673,14 +691,12 @@ static int __init init_kprobes(void)
INIT_HLIST_HEAD(&kprobe_table[i]);
INIT_HLIST_HEAD(&kretprobe_inst_table[i]);
}
atomic_set(&kprobe_count, 0);

err = arch_init_kprobes();
if (!err)
err = register_die_notifier(&kprobe_exceptions_nb);

if (!err)
err = register_page_fault_notifier(&kprobe_page_fault_nb);

return err;
}

Expand Down

0 comments on commit e6f47f9

Please sign in to comment.