diff options
author | Masami Hiramatsu <mhiramat@redhat.com> | 2009-01-06 17:41:55 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-01-06 18:59:21 -0500 |
commit | f24659d96f4e056125f14498285203d1427cb18e (patch) | |
tree | 8dc1e4e0f47b10d426449e395e81a565ad6d0118 /kernel/kprobes.c | |
parent | 0deddf436a37c18ceb26c6e3b632fb9b5f58a0c1 (diff) |
kprobes: support probing module __init function
Allow kprobes to probe module __init routines. When __init functions are
freed, kprobes which probe those functions are set to "Gone" flag. These
"Gone" probes are disarmed from the code and never be enabled.
Signed-off-by: Masami Hiramatsu <mhiramat@redhat.com>
Acked-by: Ananth N Mavinakayanahalli <ananth@in.ibm.com>
Cc: Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'kernel/kprobes.c')
-rw-r--r-- | kernel/kprobes.c | 23 |
1 files changed, 19 insertions, 4 deletions
diff --git a/kernel/kprobes.c b/kernel/kprobes.c index ddefb9fae0c8..1b9cbdc0127a 100644 --- a/kernel/kprobes.c +++ b/kernel/kprobes.c | |||
@@ -677,6 +677,16 @@ int __kprobes register_kprobe(struct kprobe *p) | |||
677 | preempt_enable(); | 677 | preempt_enable(); |
678 | return -EINVAL; | 678 | return -EINVAL; |
679 | } | 679 | } |
680 | /* | ||
681 | * If the module freed .init.text, we couldn't insert | ||
682 | * kprobes in there. | ||
683 | */ | ||
684 | if (within_module_init((unsigned long)p->addr, probed_mod) && | ||
685 | probed_mod->state != MODULE_STATE_COMING) { | ||
686 | module_put(probed_mod); | ||
687 | preempt_enable(); | ||
688 | return -EINVAL; | ||
689 | } | ||
680 | } | 690 | } |
681 | preempt_enable(); | 691 | preempt_enable(); |
682 | 692 | ||
@@ -1073,19 +1083,24 @@ static int __kprobes kprobes_module_callback(struct notifier_block *nb, | |||
1073 | struct hlist_node *node; | 1083 | struct hlist_node *node; |
1074 | struct kprobe *p; | 1084 | struct kprobe *p; |
1075 | unsigned int i; | 1085 | unsigned int i; |
1086 | int checkcore = (val == MODULE_STATE_GOING); | ||
1076 | 1087 | ||
1077 | if (val != MODULE_STATE_GOING) | 1088 | if (val != MODULE_STATE_GOING && val != MODULE_STATE_LIVE) |
1078 | return NOTIFY_DONE; | 1089 | return NOTIFY_DONE; |
1079 | 1090 | ||
1080 | /* | 1091 | /* |
1081 | * module .text section will be freed. We need to | 1092 | * When MODULE_STATE_GOING was notified, both of module .text and |
1082 | * disable kprobes which have been inserted in the section. | 1093 | * .init.text sections would be freed. When MODULE_STATE_LIVE was |
1094 | * notified, only .init.text section would be freed. We need to | ||
1095 | * disable kprobes which have been inserted in the sections. | ||
1083 | */ | 1096 | */ |
1084 | mutex_lock(&kprobe_mutex); | 1097 | mutex_lock(&kprobe_mutex); |
1085 | for (i = 0; i < KPROBE_TABLE_SIZE; i++) { | 1098 | for (i = 0; i < KPROBE_TABLE_SIZE; i++) { |
1086 | head = &kprobe_table[i]; | 1099 | head = &kprobe_table[i]; |
1087 | hlist_for_each_entry_rcu(p, node, head, hlist) | 1100 | hlist_for_each_entry_rcu(p, node, head, hlist) |
1088 | if (within_module_core((unsigned long)p->addr, mod)) { | 1101 | if (within_module_init((unsigned long)p->addr, mod) || |
1102 | (checkcore && | ||
1103 | within_module_core((unsigned long)p->addr, mod))) { | ||
1089 | /* | 1104 | /* |
1090 | * The vaddr this probe is installed will soon | 1105 | * The vaddr this probe is installed will soon |
1091 | * be vfreed buy not synced to disk. Hence, | 1106 | * be vfreed buy not synced to disk. Hence, |