aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/asm-i386/kprobes.h1
-rw-r--r--include/asm-ia64/kprobes.h1
-rw-r--r--include/asm-powerpc/kprobes.h2
-rw-r--r--include/asm-sparc64/kprobes.h1
-rw-r--r--include/asm-x86_64/kprobes.h1
-rw-r--r--kernel/kprobes.c30
6 files changed, 29 insertions, 7 deletions
diff --git a/include/asm-i386/kprobes.h b/include/asm-i386/kprobes.h
index 57d157c5cf89..0730a20f6db8 100644
--- a/include/asm-i386/kprobes.h
+++ b/include/asm-i386/kprobes.h
@@ -44,6 +44,7 @@ typedef u8 kprobe_opcode_t;
44 44
45#define JPROBE_ENTRY(pentry) (kprobe_opcode_t *)pentry 45#define JPROBE_ENTRY(pentry) (kprobe_opcode_t *)pentry
46#define ARCH_SUPPORTS_KRETPROBES 46#define ARCH_SUPPORTS_KRETPROBES
47#define ARCH_INACTIVE_KPROBE_COUNT 0
47 48
48void arch_remove_kprobe(struct kprobe *p); 49void arch_remove_kprobe(struct kprobe *p);
49void kretprobe_trampoline(void); 50void kretprobe_trampoline(void);
diff --git a/include/asm-ia64/kprobes.h b/include/asm-ia64/kprobes.h
index 8c0fc227f0fb..2418a787c405 100644
--- a/include/asm-ia64/kprobes.h
+++ b/include/asm-ia64/kprobes.h
@@ -82,6 +82,7 @@ struct kprobe_ctlblk {
82#define JPROBE_ENTRY(pentry) (kprobe_opcode_t *)pentry 82#define JPROBE_ENTRY(pentry) (kprobe_opcode_t *)pentry
83 83
84#define ARCH_SUPPORTS_KRETPROBES 84#define ARCH_SUPPORTS_KRETPROBES
85#define ARCH_INACTIVE_KPROBE_COUNT 1
85 86
86#define SLOT0_OPCODE_SHIFT (37) 87#define SLOT0_OPCODE_SHIFT (37)
87#define SLOT1_p1_OPCODE_SHIFT (37 - (64-46)) 88#define SLOT1_p1_OPCODE_SHIFT (37 - (64-46))
diff --git a/include/asm-powerpc/kprobes.h b/include/asm-powerpc/kprobes.h
index f466bc804f41..2d0af52c823d 100644
--- a/include/asm-powerpc/kprobes.h
+++ b/include/asm-powerpc/kprobes.h
@@ -50,6 +50,8 @@ typedef unsigned int kprobe_opcode_t;
50 IS_TWI(instr) || IS_TDI(instr)) 50 IS_TWI(instr) || IS_TDI(instr))
51 51
52#define ARCH_SUPPORTS_KRETPROBES 52#define ARCH_SUPPORTS_KRETPROBES
53#define ARCH_INACTIVE_KPROBE_COUNT 1
54
53void kretprobe_trampoline(void); 55void kretprobe_trampoline(void);
54extern void arch_remove_kprobe(struct kprobe *p); 56extern void arch_remove_kprobe(struct kprobe *p);
55 57
diff --git a/include/asm-sparc64/kprobes.h b/include/asm-sparc64/kprobes.h
index e9bb26f770ed..15065af566c2 100644
--- a/include/asm-sparc64/kprobes.h
+++ b/include/asm-sparc64/kprobes.h
@@ -12,6 +12,7 @@ typedef u32 kprobe_opcode_t;
12 12
13#define JPROBE_ENTRY(pentry) (kprobe_opcode_t *)pentry 13#define JPROBE_ENTRY(pentry) (kprobe_opcode_t *)pentry
14#define arch_remove_kprobe(p) do {} while (0) 14#define arch_remove_kprobe(p) do {} while (0)
15#define ARCH_INACTIVE_KPROBE_COUNT 0
15 16
16/* Architecture specific copy of original instruction*/ 17/* Architecture specific copy of original instruction*/
17struct arch_specific_insn { 18struct arch_specific_insn {
diff --git a/include/asm-x86_64/kprobes.h b/include/asm-x86_64/kprobes.h
index 98a1e95ddb98..d36febd9bb18 100644
--- a/include/asm-x86_64/kprobes.h
+++ b/include/asm-x86_64/kprobes.h
@@ -43,6 +43,7 @@ typedef u8 kprobe_opcode_t;
43 43
44#define JPROBE_ENTRY(pentry) (kprobe_opcode_t *)pentry 44#define JPROBE_ENTRY(pentry) (kprobe_opcode_t *)pentry
45#define ARCH_SUPPORTS_KRETPROBES 45#define ARCH_SUPPORTS_KRETPROBES
46#define ARCH_INACTIVE_KPROBE_COUNT 1
46 47
47void kretprobe_trampoline(void); 48void kretprobe_trampoline(void);
48extern void arch_remove_kprobe(struct kprobe *p); 49extern void arch_remove_kprobe(struct kprobe *p);
diff --git a/kernel/kprobes.c b/kernel/kprobes.c
index 507f26e7ae7c..64aab081153b 100644
--- a/kernel/kprobes.c
+++ b/kernel/kprobes.c
@@ -47,11 +47,17 @@
47 47
48static struct hlist_head kprobe_table[KPROBE_TABLE_SIZE]; 48static struct hlist_head kprobe_table[KPROBE_TABLE_SIZE];
49static struct hlist_head kretprobe_inst_table[KPROBE_TABLE_SIZE]; 49static struct hlist_head kretprobe_inst_table[KPROBE_TABLE_SIZE];
50static atomic_t kprobe_count;
50 51
51DEFINE_MUTEX(kprobe_mutex); /* Protects kprobe_table */ 52DEFINE_MUTEX(kprobe_mutex); /* Protects kprobe_table */
52DEFINE_SPINLOCK(kretprobe_lock); /* Protects kretprobe_inst_table */ 53DEFINE_SPINLOCK(kretprobe_lock); /* Protects kretprobe_inst_table */
53static DEFINE_PER_CPU(struct kprobe *, kprobe_instance) = NULL; 54static DEFINE_PER_CPU(struct kprobe *, kprobe_instance) = NULL;
54 55
56static struct notifier_block kprobe_page_fault_nb = {
57 .notifier_call = kprobe_exceptions_notify,
58 .priority = 0x7fffffff /* we need to notified first */
59};
60
55#ifdef __ARCH_WANT_KPROBES_INSN_SLOT 61#ifdef __ARCH_WANT_KPROBES_INSN_SLOT
56/* 62/*
57 * kprobe->ainsn.insn points to the copy of the instruction to be 63 * kprobe->ainsn.insn points to the copy of the instruction to be
@@ -465,6 +471,8 @@ static int __kprobes __register_kprobe(struct kprobe *p,
465 old_p = get_kprobe(p->addr); 471 old_p = get_kprobe(p->addr);
466 if (old_p) { 472 if (old_p) {
467 ret = register_aggr_kprobe(old_p, p); 473 ret = register_aggr_kprobe(old_p, p);
474 if (!ret)
475 atomic_inc(&kprobe_count);
468 goto out; 476 goto out;
469 } 477 }
470 478
@@ -475,6 +483,10 @@ static int __kprobes __register_kprobe(struct kprobe *p,
475 hlist_add_head_rcu(&p->hlist, 483 hlist_add_head_rcu(&p->hlist,
476 &kprobe_table[hash_ptr(p->addr, KPROBE_HASH_BITS)]); 484 &kprobe_table[hash_ptr(p->addr, KPROBE_HASH_BITS)]);
477 485
486 if (atomic_add_return(1, &kprobe_count) == \
487 (ARCH_INACTIVE_KPROBE_COUNT + 1))
488 register_page_fault_notifier(&kprobe_page_fault_nb);
489
478 arch_arm_kprobe(p); 490 arch_arm_kprobe(p);
479 491
480out: 492out:
@@ -553,6 +565,16 @@ valid_p:
553 } 565 }
554 mutex_unlock(&kprobe_mutex); 566 mutex_unlock(&kprobe_mutex);
555 } 567 }
568
569 /* Call unregister_page_fault_notifier()
570 * if no probes are active
571 */
572 mutex_lock(&kprobe_mutex);
573 if (atomic_add_return(-1, &kprobe_count) == \
574 ARCH_INACTIVE_KPROBE_COUNT)
575 unregister_page_fault_notifier(&kprobe_page_fault_nb);
576 mutex_unlock(&kprobe_mutex);
577 return;
556} 578}
557 579
558static struct notifier_block kprobe_exceptions_nb = { 580static struct notifier_block kprobe_exceptions_nb = {
@@ -560,10 +582,6 @@ static struct notifier_block kprobe_exceptions_nb = {
560 .priority = 0x7fffffff /* we need to be notified first */ 582 .priority = 0x7fffffff /* we need to be notified first */
561}; 583};
562 584
563static struct notifier_block kprobe_page_fault_nb = {
564 .notifier_call = kprobe_exceptions_notify,
565 .priority = 0x7fffffff /* we need to notified first */
566};
567 585
568int __kprobes register_jprobe(struct jprobe *jp) 586int __kprobes register_jprobe(struct jprobe *jp)
569{ 587{
@@ -673,14 +691,12 @@ static int __init init_kprobes(void)
673 INIT_HLIST_HEAD(&kprobe_table[i]); 691 INIT_HLIST_HEAD(&kprobe_table[i]);
674 INIT_HLIST_HEAD(&kretprobe_inst_table[i]); 692 INIT_HLIST_HEAD(&kretprobe_inst_table[i]);
675 } 693 }
694 atomic_set(&kprobe_count, 0);
676 695
677 err = arch_init_kprobes(); 696 err = arch_init_kprobes();
678 if (!err) 697 if (!err)
679 err = register_die_notifier(&kprobe_exceptions_nb); 698 err = register_die_notifier(&kprobe_exceptions_nb);
680 699
681 if (!err)
682 err = register_page_fault_notifier(&kprobe_page_fault_nb);
683
684 return err; 700 return err;
685} 701}
686 702