aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--kernel/kprobes.c23
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,