diff options
-rw-r--r-- | arch/avr32/kernel/kprobes.c | 2 | ||||
-rw-r--r-- | arch/ia64/kernel/kprobes.c | 2 | ||||
-rw-r--r-- | arch/powerpc/kernel/kprobes.c | 2 | ||||
-rw-r--r-- | arch/s390/kernel/kprobes.c | 2 | ||||
-rw-r--r-- | arch/sparc64/kernel/kprobes.c | 2 | ||||
-rw-r--r-- | arch/x86/kernel/kprobes_32.c | 7 | ||||
-rw-r--r-- | arch/x86/kernel/kprobes_64.c | 7 | ||||
-rw-r--r-- | arch/x86/kernel/process_64.c | 2 | ||||
-rw-r--r-- | include/asm-avr32/kprobes.h | 2 | ||||
-rw-r--r-- | include/asm-ia64/kprobes.h | 1 | ||||
-rw-r--r-- | include/asm-powerpc/kprobes.h | 1 | ||||
-rw-r--r-- | include/asm-s390/kprobes.h | 1 | ||||
-rw-r--r-- | include/asm-sparc64/kprobes.h | 2 | ||||
-rw-r--r-- | include/asm-x86/kprobes_32.h | 2 | ||||
-rw-r--r-- | include/asm-x86/kprobes_64.h | 1 | ||||
-rw-r--r-- | include/linux/kprobes.h | 6 | ||||
-rw-r--r-- | kernel/kprobes.c | 23 |
17 files changed, 64 insertions, 1 deletions
diff --git a/arch/avr32/kernel/kprobes.c b/arch/avr32/kernel/kprobes.c index 4942ee662e0b..20b1c9d8f945 100644 --- a/arch/avr32/kernel/kprobes.c +++ b/arch/avr32/kernel/kprobes.c | |||
@@ -22,6 +22,8 @@ DEFINE_PER_CPU(struct kprobe *, current_kprobe); | |||
22 | static unsigned long kprobe_status; | 22 | static unsigned long kprobe_status; |
23 | static struct pt_regs jprobe_saved_regs; | 23 | static struct pt_regs jprobe_saved_regs; |
24 | 24 | ||
25 | struct kretprobe_blackpoint kretprobe_blacklist[] = {{NULL, NULL}}; | ||
26 | |||
25 | int __kprobes arch_prepare_kprobe(struct kprobe *p) | 27 | int __kprobes arch_prepare_kprobe(struct kprobe *p) |
26 | { | 28 | { |
27 | int ret = 0; | 29 | int ret = 0; |
diff --git a/arch/ia64/kernel/kprobes.c b/arch/ia64/kernel/kprobes.c index 5dc98b5abcfb..5fd65d8302c8 100644 --- a/arch/ia64/kernel/kprobes.c +++ b/arch/ia64/kernel/kprobes.c | |||
@@ -40,6 +40,8 @@ extern void jprobe_inst_return(void); | |||
40 | DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL; | 40 | DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL; |
41 | DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk); | 41 | DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk); |
42 | 42 | ||
43 | struct kretprobe_blackpoint kretprobe_blacklist[] = {{NULL, NULL}}; | ||
44 | |||
43 | enum instruction_type {A, I, M, F, B, L, X, u}; | 45 | enum instruction_type {A, I, M, F, B, L, X, u}; |
44 | static enum instruction_type bundle_encoding[32][3] = { | 46 | static enum instruction_type bundle_encoding[32][3] = { |
45 | { M, I, I }, /* 00 */ | 47 | { M, I, I }, /* 00 */ |
diff --git a/arch/powerpc/kernel/kprobes.c b/arch/powerpc/kernel/kprobes.c index 440f5a87271f..5338e4855712 100644 --- a/arch/powerpc/kernel/kprobes.c +++ b/arch/powerpc/kernel/kprobes.c | |||
@@ -38,6 +38,8 @@ | |||
38 | DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL; | 38 | DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL; |
39 | DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk); | 39 | DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk); |
40 | 40 | ||
41 | struct kretprobe_blackpoint kretprobe_blacklist[] = {{NULL, NULL}}; | ||
42 | |||
41 | int __kprobes arch_prepare_kprobe(struct kprobe *p) | 43 | int __kprobes arch_prepare_kprobe(struct kprobe *p) |
42 | { | 44 | { |
43 | int ret = 0; | 45 | int ret = 0; |
diff --git a/arch/s390/kernel/kprobes.c b/arch/s390/kernel/kprobes.c index e40373d9fbce..c5549a206284 100644 --- a/arch/s390/kernel/kprobes.c +++ b/arch/s390/kernel/kprobes.c | |||
@@ -33,6 +33,8 @@ | |||
33 | DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL; | 33 | DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL; |
34 | DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk); | 34 | DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk); |
35 | 35 | ||
36 | struct kretprobe_blackpoint kretprobe_blacklist[] = {{NULL, NULL}}; | ||
37 | |||
36 | int __kprobes arch_prepare_kprobe(struct kprobe *p) | 38 | int __kprobes arch_prepare_kprobe(struct kprobe *p) |
37 | { | 39 | { |
38 | /* Make sure the probe isn't going on a difficult instruction */ | 40 | /* Make sure the probe isn't going on a difficult instruction */ |
diff --git a/arch/sparc64/kernel/kprobes.c b/arch/sparc64/kernel/kprobes.c index c93a15b785fa..d94f901d321e 100644 --- a/arch/sparc64/kernel/kprobes.c +++ b/arch/sparc64/kernel/kprobes.c | |||
@@ -42,6 +42,8 @@ | |||
42 | DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL; | 42 | DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL; |
43 | DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk); | 43 | DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk); |
44 | 44 | ||
45 | struct kretprobe_blackpoint kretprobe_blacklist[] = {{NULL, NULL}}; | ||
46 | |||
45 | int __kprobes arch_prepare_kprobe(struct kprobe *p) | 47 | int __kprobes arch_prepare_kprobe(struct kprobe *p) |
46 | { | 48 | { |
47 | p->ainsn.insn[0] = *p->addr; | 49 | p->ainsn.insn[0] = *p->addr; |
diff --git a/arch/x86/kernel/kprobes_32.c b/arch/x86/kernel/kprobes_32.c index 06b86e5617f6..90f778c04b3f 100644 --- a/arch/x86/kernel/kprobes_32.c +++ b/arch/x86/kernel/kprobes_32.c | |||
@@ -41,6 +41,13 @@ void jprobe_return_end(void); | |||
41 | DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL; | 41 | DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL; |
42 | DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk); | 42 | DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk); |
43 | 43 | ||
44 | struct kretprobe_blackpoint kretprobe_blacklist[] = { | ||
45 | {"__switch_to", }, /* This function switches only current task, but | ||
46 | doesn't switch kernel stack.*/ | ||
47 | {NULL, NULL} /* Terminator */ | ||
48 | }; | ||
49 | const int kretprobe_blacklist_size = ARRAY_SIZE(kretprobe_blacklist); | ||
50 | |||
44 | /* insert a jmp code */ | 51 | /* insert a jmp code */ |
45 | static __always_inline void set_jmp_op(void *from, void *to) | 52 | static __always_inline void set_jmp_op(void *from, void *to) |
46 | { | 53 | { |
diff --git a/arch/x86/kernel/kprobes_64.c b/arch/x86/kernel/kprobes_64.c index 7c16506d681f..681b801c5e26 100644 --- a/arch/x86/kernel/kprobes_64.c +++ b/arch/x86/kernel/kprobes_64.c | |||
@@ -48,6 +48,13 @@ static void __kprobes arch_copy_kprobe(struct kprobe *p); | |||
48 | DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL; | 48 | DEFINE_PER_CPU(struct kprobe *, current_kprobe) = NULL; |
49 | DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk); | 49 | DEFINE_PER_CPU(struct kprobe_ctlblk, kprobe_ctlblk); |
50 | 50 | ||
51 | struct kretprobe_blackpoint kretprobe_blacklist[] = { | ||
52 | {"__switch_to", }, /* This function switches only current task, but | ||
53 | doesn't switch kernel stack.*/ | ||
54 | {NULL, NULL} /* Terminator */ | ||
55 | }; | ||
56 | const int kretprobe_blacklist_size = ARRAY_SIZE(kretprobe_blacklist); | ||
57 | |||
51 | /* | 58 | /* |
52 | * returns non-zero if opcode modifies the interrupt flag. | 59 | * returns non-zero if opcode modifies the interrupt flag. |
53 | */ | 60 | */ |
diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c index 7352d4b377e6..6309b275cb9c 100644 --- a/arch/x86/kernel/process_64.c +++ b/arch/x86/kernel/process_64.c | |||
@@ -581,7 +581,7 @@ static inline void __switch_to_xtra(struct task_struct *prev_p, | |||
581 | * | 581 | * |
582 | * Kprobes not supported here. Set the probe on schedule instead. | 582 | * Kprobes not supported here. Set the probe on schedule instead. |
583 | */ | 583 | */ |
584 | __kprobes struct task_struct * | 584 | struct task_struct * |
585 | __switch_to(struct task_struct *prev_p, struct task_struct *next_p) | 585 | __switch_to(struct task_struct *prev_p, struct task_struct *next_p) |
586 | { | 586 | { |
587 | struct thread_struct *prev = &prev_p->thread, | 587 | struct thread_struct *prev = &prev_p->thread, |
diff --git a/include/asm-avr32/kprobes.h b/include/asm-avr32/kprobes.h index 0f3e636e6e4d..996cb656474e 100644 --- a/include/asm-avr32/kprobes.h +++ b/include/asm-avr32/kprobes.h | |||
@@ -17,6 +17,8 @@ typedef u16 kprobe_opcode_t; | |||
17 | #define BREAKPOINT_INSTRUCTION 0xd673 /* breakpoint */ | 17 | #define BREAKPOINT_INSTRUCTION 0xd673 /* breakpoint */ |
18 | #define MAX_INSN_SIZE 2 | 18 | #define MAX_INSN_SIZE 2 |
19 | 19 | ||
20 | #define kretprobe_blacklist_size 0 | ||
21 | |||
20 | #define arch_remove_kprobe(p) do { } while (0) | 22 | #define arch_remove_kprobe(p) do { } while (0) |
21 | 23 | ||
22 | /* Architecture specific copy of original instruction */ | 24 | /* Architecture specific copy of original instruction */ |
diff --git a/include/asm-ia64/kprobes.h b/include/asm-ia64/kprobes.h index 6c79edf24d73..a93ce9ef07ff 100644 --- a/include/asm-ia64/kprobes.h +++ b/include/asm-ia64/kprobes.h | |||
@@ -83,6 +83,7 @@ struct kprobe_ctlblk { | |||
83 | }; | 83 | }; |
84 | 84 | ||
85 | #define ARCH_SUPPORTS_KRETPROBES | 85 | #define ARCH_SUPPORTS_KRETPROBES |
86 | #define kretprobe_blacklist_size 0 | ||
86 | 87 | ||
87 | #define SLOT0_OPCODE_SHIFT (37) | 88 | #define SLOT0_OPCODE_SHIFT (37) |
88 | #define SLOT1_p1_OPCODE_SHIFT (37 - (64-46)) | 89 | #define SLOT1_p1_OPCODE_SHIFT (37 - (64-46)) |
diff --git a/include/asm-powerpc/kprobes.h b/include/asm-powerpc/kprobes.h index c16973d5de62..afabad230dbb 100644 --- a/include/asm-powerpc/kprobes.h +++ b/include/asm-powerpc/kprobes.h | |||
@@ -82,6 +82,7 @@ typedef unsigned int kprobe_opcode_t; | |||
82 | 82 | ||
83 | #define ARCH_SUPPORTS_KRETPROBES | 83 | #define ARCH_SUPPORTS_KRETPROBES |
84 | #define flush_insn_slot(p) do { } while (0) | 84 | #define flush_insn_slot(p) do { } while (0) |
85 | #define kretprobe_blacklist_size 0 | ||
85 | 86 | ||
86 | void kretprobe_trampoline(void); | 87 | void kretprobe_trampoline(void); |
87 | extern void arch_remove_kprobe(struct kprobe *p); | 88 | extern void arch_remove_kprobe(struct kprobe *p); |
diff --git a/include/asm-s390/kprobes.h b/include/asm-s390/kprobes.h index 8bc67cc9ffd2..948db3d0d05c 100644 --- a/include/asm-s390/kprobes.h +++ b/include/asm-s390/kprobes.h | |||
@@ -47,6 +47,7 @@ typedef u16 kprobe_opcode_t; | |||
47 | : (((unsigned long)current_thread_info()) + THREAD_SIZE - (ADDR))) | 47 | : (((unsigned long)current_thread_info()) + THREAD_SIZE - (ADDR))) |
48 | 48 | ||
49 | #define ARCH_SUPPORTS_KRETPROBES | 49 | #define ARCH_SUPPORTS_KRETPROBES |
50 | #define kretprobe_blacklist_size 0 | ||
50 | 51 | ||
51 | #define KPROBE_SWAP_INST 0x10 | 52 | #define KPROBE_SWAP_INST 0x10 |
52 | 53 | ||
diff --git a/include/asm-sparc64/kprobes.h b/include/asm-sparc64/kprobes.h index a04145b77f96..5020eaf67c29 100644 --- a/include/asm-sparc64/kprobes.h +++ b/include/asm-sparc64/kprobes.h | |||
@@ -10,6 +10,8 @@ typedef u32 kprobe_opcode_t; | |||
10 | #define BREAKPOINT_INSTRUCTION_2 0x91d02071 /* ta 0x71 */ | 10 | #define BREAKPOINT_INSTRUCTION_2 0x91d02071 /* ta 0x71 */ |
11 | #define MAX_INSN_SIZE 2 | 11 | #define MAX_INSN_SIZE 2 |
12 | 12 | ||
13 | #define kretprobe_blacklist_size 0 | ||
14 | |||
13 | #define arch_remove_kprobe(p) do {} while (0) | 15 | #define arch_remove_kprobe(p) do {} while (0) |
14 | 16 | ||
15 | #define flush_insn_slot(p) \ | 17 | #define flush_insn_slot(p) \ |
diff --git a/include/asm-x86/kprobes_32.h b/include/asm-x86/kprobes_32.h index f2489d07ce88..b772d5b38685 100644 --- a/include/asm-x86/kprobes_32.h +++ b/include/asm-x86/kprobes_32.h | |||
@@ -45,6 +45,8 @@ typedef u8 kprobe_opcode_t; | |||
45 | #define ARCH_SUPPORTS_KRETPROBES | 45 | #define ARCH_SUPPORTS_KRETPROBES |
46 | #define flush_insn_slot(p) do { } while (0) | 46 | #define flush_insn_slot(p) do { } while (0) |
47 | 47 | ||
48 | extern const int kretprobe_blacklist_size; | ||
49 | |||
48 | void arch_remove_kprobe(struct kprobe *p); | 50 | void arch_remove_kprobe(struct kprobe *p); |
49 | void kretprobe_trampoline(void); | 51 | void kretprobe_trampoline(void); |
50 | 52 | ||
diff --git a/include/asm-x86/kprobes_64.h b/include/asm-x86/kprobes_64.h index 3f495e5308b1..53f4d8507354 100644 --- a/include/asm-x86/kprobes_64.h +++ b/include/asm-x86/kprobes_64.h | |||
@@ -42,6 +42,7 @@ typedef u8 kprobe_opcode_t; | |||
42 | : (((unsigned long)current_thread_info()) + THREAD_SIZE - (ADDR))) | 42 | : (((unsigned long)current_thread_info()) + THREAD_SIZE - (ADDR))) |
43 | 43 | ||
44 | #define ARCH_SUPPORTS_KRETPROBES | 44 | #define ARCH_SUPPORTS_KRETPROBES |
45 | extern const int kretprobe_blacklist_size; | ||
45 | 46 | ||
46 | void kretprobe_trampoline(void); | 47 | void kretprobe_trampoline(void); |
47 | extern void arch_remove_kprobe(struct kprobe *p); | 48 | extern void arch_remove_kprobe(struct kprobe *p); |
diff --git a/include/linux/kprobes.h b/include/linux/kprobes.h index 51464d12a4e5..81891581e89b 100644 --- a/include/linux/kprobes.h +++ b/include/linux/kprobes.h | |||
@@ -166,6 +166,12 @@ struct kretprobe_instance { | |||
166 | struct task_struct *task; | 166 | struct task_struct *task; |
167 | }; | 167 | }; |
168 | 168 | ||
169 | struct kretprobe_blackpoint { | ||
170 | const char *name; | ||
171 | void *addr; | ||
172 | }; | ||
173 | extern struct kretprobe_blackpoint kretprobe_blacklist[]; | ||
174 | |||
169 | static inline void kretprobe_assert(struct kretprobe_instance *ri, | 175 | static inline void kretprobe_assert(struct kretprobe_instance *ri, |
170 | unsigned long orig_ret_address, unsigned long trampoline_address) | 176 | unsigned long orig_ret_address, unsigned long trampoline_address) |
171 | { | 177 | { |
diff --git a/kernel/kprobes.c b/kernel/kprobes.c index f9798ff7899f..e3a5d817ac9b 100644 --- a/kernel/kprobes.c +++ b/kernel/kprobes.c | |||
@@ -716,6 +716,18 @@ int __kprobes register_kretprobe(struct kretprobe *rp) | |||
716 | int ret = 0; | 716 | int ret = 0; |
717 | struct kretprobe_instance *inst; | 717 | struct kretprobe_instance *inst; |
718 | int i; | 718 | int i; |
719 | void *addr = rp->kp.addr; | ||
720 | |||
721 | if (kretprobe_blacklist_size) { | ||
722 | if (addr == NULL) | ||
723 | kprobe_lookup_name(rp->kp.symbol_name, addr); | ||
724 | addr += rp->kp.offset; | ||
725 | |||
726 | for (i = 0; kretprobe_blacklist[i].name != NULL; i++) { | ||
727 | if (kretprobe_blacklist[i].addr == addr) | ||
728 | return -EINVAL; | ||
729 | } | ||
730 | } | ||
719 | 731 | ||
720 | rp->kp.pre_handler = pre_handler_kretprobe; | 732 | rp->kp.pre_handler = pre_handler_kretprobe; |
721 | rp->kp.post_handler = NULL; | 733 | rp->kp.post_handler = NULL; |
@@ -794,6 +806,17 @@ static int __init init_kprobes(void) | |||
794 | INIT_HLIST_HEAD(&kretprobe_inst_table[i]); | 806 | INIT_HLIST_HEAD(&kretprobe_inst_table[i]); |
795 | } | 807 | } |
796 | 808 | ||
809 | if (kretprobe_blacklist_size) { | ||
810 | /* lookup the function address from its name */ | ||
811 | for (i = 0; kretprobe_blacklist[i].name != NULL; i++) { | ||
812 | kprobe_lookup_name(kretprobe_blacklist[i].name, | ||
813 | kretprobe_blacklist[i].addr); | ||
814 | if (!kretprobe_blacklist[i].addr) | ||
815 | printk("kretprobe: lookup failed: %s\n", | ||
816 | kretprobe_blacklist[i].name); | ||
817 | } | ||
818 | } | ||
819 | |||
797 | /* By default, kprobes are enabled */ | 820 | /* By default, kprobes are enabled */ |
798 | kprobe_enabled = true; | 821 | kprobe_enabled = true; |
799 | 822 | ||