diff options
-rw-r--r-- | Documentation/kprobes.txt | 34 | ||||
-rw-r--r-- | arch/i386/kernel/kprobes.c | 5 | ||||
-rw-r--r-- | arch/ia64/kernel/kprobes.c | 9 | ||||
-rw-r--r-- | arch/powerpc/kernel/kprobes.c | 8 | ||||
-rw-r--r-- | arch/s390/kernel/kprobes.c | 7 | ||||
-rw-r--r-- | arch/x86_64/kernel/kprobes.c | 8 | ||||
-rw-r--r-- | include/linux/kprobes.h | 5 | ||||
-rw-r--r-- | kernel/kprobes.c | 156 |
8 files changed, 222 insertions, 10 deletions
diff --git a/Documentation/kprobes.txt b/Documentation/kprobes.txt index d71fafffce90..da5404ab7569 100644 --- a/Documentation/kprobes.txt +++ b/Documentation/kprobes.txt | |||
@@ -14,6 +14,7 @@ CONTENTS | |||
14 | 8. Kprobes Example | 14 | 8. Kprobes Example |
15 | 9. Jprobes Example | 15 | 9. Jprobes Example |
16 | 10. Kretprobes Example | 16 | 10. Kretprobes Example |
17 | Appendix A: The kprobes debugfs interface | ||
17 | 18 | ||
18 | 1. Concepts: Kprobes, Jprobes, Return Probes | 19 | 1. Concepts: Kprobes, Jprobes, Return Probes |
19 | 20 | ||
@@ -349,9 +350,12 @@ for instrumentation and error reporting.) | |||
349 | 350 | ||
350 | If the number of times a function is called does not match the number | 351 | If the number of times a function is called does not match the number |
351 | of times it returns, registering a return probe on that function may | 352 | of times it returns, registering a return probe on that function may |
352 | produce undesirable results. We have the do_exit() case covered. | 353 | produce undesirable results. In such a case, a line: |
353 | do_execve() and do_fork() are not an issue. We're unaware of other | 354 | kretprobe BUG!: Processing kretprobe d000000000041aa8 @ c00000000004f48c |
354 | specific cases where this could be a problem. | 355 | gets printed. With this information, one will be able to correlate the |
356 | exact instance of the kretprobe that caused the problem. We have the | ||
357 | do_exit() case covered. do_execve() and do_fork() are not an issue. | ||
358 | We're unaware of other specific cases where this could be a problem. | ||
355 | 359 | ||
356 | If, upon entry to or exit from a function, the CPU is running on | 360 | If, upon entry to or exit from a function, the CPU is running on |
357 | a stack other than that of the current task, registering a return | 361 | a stack other than that of the current task, registering a return |
@@ -614,3 +618,27 @@ http://www-106.ibm.com/developerworks/library/l-kprobes.html?ca=dgr-lnxw42Kprobe | |||
614 | http://www.redhat.com/magazine/005mar05/features/kprobes/ | 618 | http://www.redhat.com/magazine/005mar05/features/kprobes/ |
615 | http://www-users.cs.umn.edu/~boutcher/kprobes/ | 619 | http://www-users.cs.umn.edu/~boutcher/kprobes/ |
616 | http://www.linuxsymposium.org/2006/linuxsymposium_procv2.pdf (pages 101-115) | 620 | http://www.linuxsymposium.org/2006/linuxsymposium_procv2.pdf (pages 101-115) |
621 | |||
622 | |||
623 | Appendix A: The kprobes debugfs interface | ||
624 | |||
625 | With recent kernels (> 2.6.20) the list of registered kprobes is visible | ||
626 | under the /debug/kprobes/ directory (assuming debugfs is mounted at /debug). | ||
627 | |||
628 | /debug/kprobes/list: Lists all registered probes on the system | ||
629 | |||
630 | c015d71a k vfs_read+0x0 | ||
631 | c011a316 j do_fork+0x0 | ||
632 | c03dedc5 r tcp_v4_rcv+0x0 | ||
633 | |||
634 | The first column provides the kernel address where the probe is inserted. | ||
635 | The second column identifies the type of probe (k - kprobe, r - kretprobe | ||
636 | and j - jprobe), while the third column specifies the symbol+offset of | ||
637 | the probe. If the probed function belongs to a module, the module name | ||
638 | is also specified. | ||
639 | |||
640 | /debug/kprobes/enabled: Turn kprobes ON/OFF | ||
641 | |||
642 | Provides a knob to globally turn registered kprobes ON or OFF. By default, | ||
643 | all kprobes are enabled. By echoing "0" to this file, all registered probes | ||
644 | will be disarmed, till such time a "1" is echoed to this file. | ||
diff --git a/arch/i386/kernel/kprobes.c b/arch/i386/kernel/kprobes.c index b6a9d64c2251..dde828a333c3 100644 --- a/arch/i386/kernel/kprobes.c +++ b/arch/i386/kernel/kprobes.c | |||
@@ -743,6 +743,11 @@ int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs) | |||
743 | return 0; | 743 | return 0; |
744 | } | 744 | } |
745 | 745 | ||
746 | int __kprobes arch_trampoline_kprobe(struct kprobe *p) | ||
747 | { | ||
748 | return 0; | ||
749 | } | ||
750 | |||
746 | int __init arch_init_kprobes(void) | 751 | int __init arch_init_kprobes(void) |
747 | { | 752 | { |
748 | return 0; | 753 | return 0; |
diff --git a/arch/ia64/kernel/kprobes.c b/arch/ia64/kernel/kprobes.c index 0b72f0f94192..4f5fd0960ba7 100644 --- a/arch/ia64/kernel/kprobes.c +++ b/arch/ia64/kernel/kprobes.c | |||
@@ -1012,3 +1012,12 @@ int __init arch_init_kprobes(void) | |||
1012 | (kprobe_opcode_t *)((struct fnptr *)kretprobe_trampoline)->ip; | 1012 | (kprobe_opcode_t *)((struct fnptr *)kretprobe_trampoline)->ip; |
1013 | return register_kprobe(&trampoline_p); | 1013 | return register_kprobe(&trampoline_p); |
1014 | } | 1014 | } |
1015 | |||
1016 | int __kprobes arch_trampoline_kprobe(struct kprobe *p) | ||
1017 | { | ||
1018 | if (p->addr == | ||
1019 | (kprobe_opcode_t *)((struct fnptr *)kretprobe_trampoline)->ip) | ||
1020 | return 1; | ||
1021 | |||
1022 | return 0; | ||
1023 | } | ||
diff --git a/arch/powerpc/kernel/kprobes.c b/arch/powerpc/kernel/kprobes.c index aed58e1cb91f..088b8c6defa0 100644 --- a/arch/powerpc/kernel/kprobes.c +++ b/arch/powerpc/kernel/kprobes.c | |||
@@ -550,3 +550,11 @@ int __init arch_init_kprobes(void) | |||
550 | { | 550 | { |
551 | return register_kprobe(&trampoline_p); | 551 | return register_kprobe(&trampoline_p); |
552 | } | 552 | } |
553 | |||
554 | int __kprobes arch_trampoline_kprobe(struct kprobe *p) | ||
555 | { | ||
556 | if (p->addr == (kprobe_opcode_t *)&kretprobe_trampoline) | ||
557 | return 1; | ||
558 | |||
559 | return 0; | ||
560 | } | ||
diff --git a/arch/s390/kernel/kprobes.c b/arch/s390/kernel/kprobes.c index 9d0f0d09d473..e39333ae0fcf 100644 --- a/arch/s390/kernel/kprobes.c +++ b/arch/s390/kernel/kprobes.c | |||
@@ -661,3 +661,10 @@ int __init arch_init_kprobes(void) | |||
661 | { | 661 | { |
662 | return register_kprobe(&trampoline_p); | 662 | return register_kprobe(&trampoline_p); |
663 | } | 663 | } |
664 | |||
665 | int __kprobes arch_trampoline_kprobe(struct kprobe *p) | ||
666 | { | ||
667 | if (p->addr == (kprobe_opcode_t *) & kretprobe_trampoline) | ||
668 | return 1; | ||
669 | return 0; | ||
670 | } | ||
diff --git a/arch/x86_64/kernel/kprobes.c b/arch/x86_64/kernel/kprobes.c index f995bea6e2c1..d4a0d0ac9935 100644 --- a/arch/x86_64/kernel/kprobes.c +++ b/arch/x86_64/kernel/kprobes.c | |||
@@ -743,3 +743,11 @@ int __init arch_init_kprobes(void) | |||
743 | { | 743 | { |
744 | return register_kprobe(&trampoline_p); | 744 | return register_kprobe(&trampoline_p); |
745 | } | 745 | } |
746 | |||
747 | int __kprobes arch_trampoline_kprobe(struct kprobe *p) | ||
748 | { | ||
749 | if (p->addr == (kprobe_opcode_t *)&kretprobe_trampoline) | ||
750 | return 1; | ||
751 | |||
752 | return 0; | ||
753 | } | ||
diff --git a/include/linux/kprobes.h b/include/linux/kprobes.h index 6fc623e41fd8..23adf6075ae4 100644 --- a/include/linux/kprobes.h +++ b/include/linux/kprobes.h | |||
@@ -125,11 +125,16 @@ DECLARE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk); | |||
125 | #ifdef ARCH_SUPPORTS_KRETPROBES | 125 | #ifdef ARCH_SUPPORTS_KRETPROBES |
126 | extern void arch_prepare_kretprobe(struct kretprobe_instance *ri, | 126 | extern void arch_prepare_kretprobe(struct kretprobe_instance *ri, |
127 | struct pt_regs *regs); | 127 | struct pt_regs *regs); |
128 | extern int arch_trampoline_kprobe(struct kprobe *p); | ||
128 | #else /* ARCH_SUPPORTS_KRETPROBES */ | 129 | #else /* ARCH_SUPPORTS_KRETPROBES */ |
129 | static inline void arch_prepare_kretprobe(struct kretprobe *rp, | 130 | static inline void arch_prepare_kretprobe(struct kretprobe *rp, |
130 | struct pt_regs *regs) | 131 | struct pt_regs *regs) |
131 | { | 132 | { |
132 | } | 133 | } |
134 | static inline int arch_trampoline_kprobe(struct kprobe *p) | ||
135 | { | ||
136 | return 0; | ||
137 | } | ||
133 | #endif /* ARCH_SUPPORTS_KRETPROBES */ | 138 | #endif /* ARCH_SUPPORTS_KRETPROBES */ |
134 | /* | 139 | /* |
135 | * Function-return probe - | 140 | * Function-return probe - |
diff --git a/kernel/kprobes.c b/kernel/kprobes.c index f58f171bd65f..9e47d8c493f3 100644 --- a/kernel/kprobes.c +++ b/kernel/kprobes.c | |||
@@ -43,9 +43,11 @@ | |||
43 | #include <linux/seq_file.h> | 43 | #include <linux/seq_file.h> |
44 | #include <linux/debugfs.h> | 44 | #include <linux/debugfs.h> |
45 | #include <linux/kdebug.h> | 45 | #include <linux/kdebug.h> |
46 | |||
46 | #include <asm-generic/sections.h> | 47 | #include <asm-generic/sections.h> |
47 | #include <asm/cacheflush.h> | 48 | #include <asm/cacheflush.h> |
48 | #include <asm/errno.h> | 49 | #include <asm/errno.h> |
50 | #include <asm/uaccess.h> | ||
49 | 51 | ||
50 | #define KPROBE_HASH_BITS 6 | 52 | #define KPROBE_HASH_BITS 6 |
51 | #define KPROBE_TABLE_SIZE (1 << KPROBE_HASH_BITS) | 53 | #define KPROBE_TABLE_SIZE (1 << KPROBE_HASH_BITS) |
@@ -64,6 +66,9 @@ static struct hlist_head kprobe_table[KPROBE_TABLE_SIZE]; | |||
64 | static struct hlist_head kretprobe_inst_table[KPROBE_TABLE_SIZE]; | 66 | static struct hlist_head kretprobe_inst_table[KPROBE_TABLE_SIZE]; |
65 | static atomic_t kprobe_count; | 67 | static atomic_t kprobe_count; |
66 | 68 | ||
69 | /* NOTE: change this value only with kprobe_mutex held */ | ||
70 | static bool kprobe_enabled; | ||
71 | |||
67 | DEFINE_MUTEX(kprobe_mutex); /* Protects kprobe_table */ | 72 | DEFINE_MUTEX(kprobe_mutex); /* Protects kprobe_table */ |
68 | DEFINE_SPINLOCK(kretprobe_lock); /* Protects kretprobe_inst_table */ | 73 | DEFINE_SPINLOCK(kretprobe_lock); /* Protects kretprobe_inst_table */ |
69 | static DEFINE_PER_CPU(struct kprobe *, kprobe_instance) = NULL; | 74 | static DEFINE_PER_CPU(struct kprobe *, kprobe_instance) = NULL; |
@@ -564,12 +569,13 @@ static int __kprobes __register_kprobe(struct kprobe *p, | |||
564 | hlist_add_head_rcu(&p->hlist, | 569 | hlist_add_head_rcu(&p->hlist, |
565 | &kprobe_table[hash_ptr(p->addr, KPROBE_HASH_BITS)]); | 570 | &kprobe_table[hash_ptr(p->addr, KPROBE_HASH_BITS)]); |
566 | 571 | ||
567 | if (atomic_add_return(1, &kprobe_count) == \ | 572 | if (kprobe_enabled) { |
573 | if (atomic_add_return(1, &kprobe_count) == \ | ||
568 | (ARCH_INACTIVE_KPROBE_COUNT + 1)) | 574 | (ARCH_INACTIVE_KPROBE_COUNT + 1)) |
569 | register_page_fault_notifier(&kprobe_page_fault_nb); | 575 | register_page_fault_notifier(&kprobe_page_fault_nb); |
570 | |||
571 | arch_arm_kprobe(p); | ||
572 | 576 | ||
577 | arch_arm_kprobe(p); | ||
578 | } | ||
573 | out: | 579 | out: |
574 | mutex_unlock(&kprobe_mutex); | 580 | mutex_unlock(&kprobe_mutex); |
575 | 581 | ||
@@ -607,8 +613,13 @@ valid_p: | |||
607 | if (old_p == p || | 613 | if (old_p == p || |
608 | (old_p->pre_handler == aggr_pre_handler && | 614 | (old_p->pre_handler == aggr_pre_handler && |
609 | p->list.next == &old_p->list && p->list.prev == &old_p->list)) { | 615 | p->list.next == &old_p->list && p->list.prev == &old_p->list)) { |
610 | /* Only probe on the hash list */ | 616 | /* |
611 | arch_disarm_kprobe(p); | 617 | * Only probe on the hash list. Disarm only if kprobes are |
618 | * enabled - otherwise, the breakpoint would already have | ||
619 | * been removed. We save on flushing icache. | ||
620 | */ | ||
621 | if (kprobe_enabled) | ||
622 | arch_disarm_kprobe(p); | ||
612 | hlist_del_rcu(&old_p->hlist); | 623 | hlist_del_rcu(&old_p->hlist); |
613 | cleanup_p = 1; | 624 | cleanup_p = 1; |
614 | } else { | 625 | } else { |
@@ -797,6 +808,9 @@ static int __init init_kprobes(void) | |||
797 | } | 808 | } |
798 | atomic_set(&kprobe_count, 0); | 809 | atomic_set(&kprobe_count, 0); |
799 | 810 | ||
811 | /* By default, kprobes are enabled */ | ||
812 | kprobe_enabled = true; | ||
813 | |||
800 | err = arch_init_kprobes(); | 814 | err = arch_init_kprobes(); |
801 | if (!err) | 815 | if (!err) |
802 | err = register_die_notifier(&kprobe_exceptions_nb); | 816 | err = register_die_notifier(&kprobe_exceptions_nb); |
@@ -806,7 +820,7 @@ static int __init init_kprobes(void) | |||
806 | 820 | ||
807 | #ifdef CONFIG_DEBUG_FS | 821 | #ifdef CONFIG_DEBUG_FS |
808 | static void __kprobes report_probe(struct seq_file *pi, struct kprobe *p, | 822 | static void __kprobes report_probe(struct seq_file *pi, struct kprobe *p, |
809 | const char *sym, int offset,char *modname) | 823 | const char *sym, int offset,char *modname) |
810 | { | 824 | { |
811 | char *kprobe_type; | 825 | char *kprobe_type; |
812 | 826 | ||
@@ -885,9 +899,130 @@ static struct file_operations debugfs_kprobes_operations = { | |||
885 | .release = seq_release, | 899 | .release = seq_release, |
886 | }; | 900 | }; |
887 | 901 | ||
902 | static void __kprobes enable_all_kprobes(void) | ||
903 | { | ||
904 | struct hlist_head *head; | ||
905 | struct hlist_node *node; | ||
906 | struct kprobe *p; | ||
907 | unsigned int i; | ||
908 | |||
909 | mutex_lock(&kprobe_mutex); | ||
910 | |||
911 | /* If kprobes are already enabled, just return */ | ||
912 | if (kprobe_enabled) | ||
913 | goto already_enabled; | ||
914 | |||
915 | /* | ||
916 | * Re-register the page fault notifier only if there are any | ||
917 | * active probes at the time of enabling kprobes globally | ||
918 | */ | ||
919 | if (atomic_read(&kprobe_count) > ARCH_INACTIVE_KPROBE_COUNT) | ||
920 | register_page_fault_notifier(&kprobe_page_fault_nb); | ||
921 | |||
922 | for (i = 0; i < KPROBE_TABLE_SIZE; i++) { | ||
923 | head = &kprobe_table[i]; | ||
924 | hlist_for_each_entry_rcu(p, node, head, hlist) | ||
925 | arch_arm_kprobe(p); | ||
926 | } | ||
927 | |||
928 | kprobe_enabled = true; | ||
929 | printk(KERN_INFO "Kprobes globally enabled\n"); | ||
930 | |||
931 | already_enabled: | ||
932 | mutex_unlock(&kprobe_mutex); | ||
933 | return; | ||
934 | } | ||
935 | |||
936 | static void __kprobes disable_all_kprobes(void) | ||
937 | { | ||
938 | struct hlist_head *head; | ||
939 | struct hlist_node *node; | ||
940 | struct kprobe *p; | ||
941 | unsigned int i; | ||
942 | |||
943 | mutex_lock(&kprobe_mutex); | ||
944 | |||
945 | /* If kprobes are already disabled, just return */ | ||
946 | if (!kprobe_enabled) | ||
947 | goto already_disabled; | ||
948 | |||
949 | kprobe_enabled = false; | ||
950 | printk(KERN_INFO "Kprobes globally disabled\n"); | ||
951 | for (i = 0; i < KPROBE_TABLE_SIZE; i++) { | ||
952 | head = &kprobe_table[i]; | ||
953 | hlist_for_each_entry_rcu(p, node, head, hlist) { | ||
954 | if (!arch_trampoline_kprobe(p)) | ||
955 | arch_disarm_kprobe(p); | ||
956 | } | ||
957 | } | ||
958 | |||
959 | mutex_unlock(&kprobe_mutex); | ||
960 | /* Allow all currently running kprobes to complete */ | ||
961 | synchronize_sched(); | ||
962 | |||
963 | mutex_lock(&kprobe_mutex); | ||
964 | /* Unconditionally unregister the page_fault notifier */ | ||
965 | unregister_page_fault_notifier(&kprobe_page_fault_nb); | ||
966 | |||
967 | already_disabled: | ||
968 | mutex_unlock(&kprobe_mutex); | ||
969 | return; | ||
970 | } | ||
971 | |||
972 | /* | ||
973 | * XXX: The debugfs bool file interface doesn't allow for callbacks | ||
974 | * when the bool state is switched. We can reuse that facility when | ||
975 | * available | ||
976 | */ | ||
977 | static ssize_t read_enabled_file_bool(struct file *file, | ||
978 | char __user *user_buf, size_t count, loff_t *ppos) | ||
979 | { | ||
980 | char buf[3]; | ||
981 | |||
982 | if (kprobe_enabled) | ||
983 | buf[0] = '1'; | ||
984 | else | ||
985 | buf[0] = '0'; | ||
986 | buf[1] = '\n'; | ||
987 | buf[2] = 0x00; | ||
988 | return simple_read_from_buffer(user_buf, count, ppos, buf, 2); | ||
989 | } | ||
990 | |||
991 | static ssize_t write_enabled_file_bool(struct file *file, | ||
992 | const char __user *user_buf, size_t count, loff_t *ppos) | ||
993 | { | ||
994 | char buf[32]; | ||
995 | int buf_size; | ||
996 | |||
997 | buf_size = min(count, (sizeof(buf)-1)); | ||
998 | if (copy_from_user(buf, user_buf, buf_size)) | ||
999 | return -EFAULT; | ||
1000 | |||
1001 | switch (buf[0]) { | ||
1002 | case 'y': | ||
1003 | case 'Y': | ||
1004 | case '1': | ||
1005 | enable_all_kprobes(); | ||
1006 | break; | ||
1007 | case 'n': | ||
1008 | case 'N': | ||
1009 | case '0': | ||
1010 | disable_all_kprobes(); | ||
1011 | break; | ||
1012 | } | ||
1013 | |||
1014 | return count; | ||
1015 | } | ||
1016 | |||
1017 | static struct file_operations fops_kp = { | ||
1018 | .read = read_enabled_file_bool, | ||
1019 | .write = write_enabled_file_bool, | ||
1020 | }; | ||
1021 | |||
888 | static int __kprobes debugfs_kprobe_init(void) | 1022 | static int __kprobes debugfs_kprobe_init(void) |
889 | { | 1023 | { |
890 | struct dentry *dir, *file; | 1024 | struct dentry *dir, *file; |
1025 | unsigned int value = 1; | ||
891 | 1026 | ||
892 | dir = debugfs_create_dir("kprobes", NULL); | 1027 | dir = debugfs_create_dir("kprobes", NULL); |
893 | if (!dir) | 1028 | if (!dir) |
@@ -900,6 +1035,13 @@ static int __kprobes debugfs_kprobe_init(void) | |||
900 | return -ENOMEM; | 1035 | return -ENOMEM; |
901 | } | 1036 | } |
902 | 1037 | ||
1038 | file = debugfs_create_file("enabled", 0600, dir, | ||
1039 | &value, &fops_kp); | ||
1040 | if (!file) { | ||
1041 | debugfs_remove(dir); | ||
1042 | return -ENOMEM; | ||
1043 | } | ||
1044 | |||
903 | return 0; | 1045 | return 0; |
904 | } | 1046 | } |
905 | 1047 | ||