aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/kprobes.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/kprobes.c')
-rw-r--r--kernel/kprobes.c26
1 files changed, 16 insertions, 10 deletions
diff --git a/kernel/kprobes.c b/kernel/kprobes.c
index 99865c33a60d..9737a76e106f 100644
--- a/kernel/kprobes.c
+++ b/kernel/kprobes.c
@@ -1145,14 +1145,13 @@ int __kprobes register_kprobe(struct kprobe *p)
1145 if (ret) 1145 if (ret)
1146 return ret; 1146 return ret;
1147 1147
1148 jump_label_lock();
1148 preempt_disable(); 1149 preempt_disable();
1149 if (!kernel_text_address((unsigned long) p->addr) || 1150 if (!kernel_text_address((unsigned long) p->addr) ||
1150 in_kprobes_functions((unsigned long) p->addr) || 1151 in_kprobes_functions((unsigned long) p->addr) ||
1151 ftrace_text_reserved(p->addr, p->addr) || 1152 ftrace_text_reserved(p->addr, p->addr) ||
1152 jump_label_text_reserved(p->addr, p->addr)) { 1153 jump_label_text_reserved(p->addr, p->addr))
1153 preempt_enable(); 1154 goto fail_with_jump_label;
1154 return -EINVAL;
1155 }
1156 1155
1157 /* User can pass only KPROBE_FLAG_DISABLED to register_kprobe */ 1156 /* User can pass only KPROBE_FLAG_DISABLED to register_kprobe */
1158 p->flags &= KPROBE_FLAG_DISABLED; 1157 p->flags &= KPROBE_FLAG_DISABLED;
@@ -1166,10 +1165,9 @@ int __kprobes register_kprobe(struct kprobe *p)
1166 * We must hold a refcount of the probed module while updating 1165 * We must hold a refcount of the probed module while updating
1167 * its code to prohibit unexpected unloading. 1166 * its code to prohibit unexpected unloading.
1168 */ 1167 */
1169 if (unlikely(!try_module_get(probed_mod))) { 1168 if (unlikely(!try_module_get(probed_mod)))
1170 preempt_enable(); 1169 goto fail_with_jump_label;
1171 return -EINVAL; 1170
1172 }
1173 /* 1171 /*
1174 * If the module freed .init.text, we couldn't insert 1172 * If the module freed .init.text, we couldn't insert
1175 * kprobes in there. 1173 * kprobes in there.
@@ -1177,16 +1175,18 @@ int __kprobes register_kprobe(struct kprobe *p)
1177 if (within_module_init((unsigned long)p->addr, probed_mod) && 1175 if (within_module_init((unsigned long)p->addr, probed_mod) &&
1178 probed_mod->state != MODULE_STATE_COMING) { 1176 probed_mod->state != MODULE_STATE_COMING) {
1179 module_put(probed_mod); 1177 module_put(probed_mod);
1180 preempt_enable(); 1178 goto fail_with_jump_label;
1181 return -EINVAL;
1182 } 1179 }
1183 } 1180 }
1184 preempt_enable(); 1181 preempt_enable();
1182 jump_label_unlock();
1185 1183
1186 p->nmissed = 0; 1184 p->nmissed = 0;
1187 INIT_LIST_HEAD(&p->list); 1185 INIT_LIST_HEAD(&p->list);
1188 mutex_lock(&kprobe_mutex); 1186 mutex_lock(&kprobe_mutex);
1189 1187
1188 jump_label_lock(); /* needed to call jump_label_text_reserved() */
1189
1190 get_online_cpus(); /* For avoiding text_mutex deadlock. */ 1190 get_online_cpus(); /* For avoiding text_mutex deadlock. */
1191 mutex_lock(&text_mutex); 1191 mutex_lock(&text_mutex);
1192 1192
@@ -1214,12 +1214,18 @@ int __kprobes register_kprobe(struct kprobe *p)
1214out: 1214out:
1215 mutex_unlock(&text_mutex); 1215 mutex_unlock(&text_mutex);
1216 put_online_cpus(); 1216 put_online_cpus();
1217 jump_label_unlock();
1217 mutex_unlock(&kprobe_mutex); 1218 mutex_unlock(&kprobe_mutex);
1218 1219
1219 if (probed_mod) 1220 if (probed_mod)
1220 module_put(probed_mod); 1221 module_put(probed_mod);
1221 1222
1222 return ret; 1223 return ret;
1224
1225fail_with_jump_label:
1226 preempt_enable();
1227 jump_label_unlock();
1228 return -EINVAL;
1223} 1229}
1224EXPORT_SYMBOL_GPL(register_kprobe); 1230EXPORT_SYMBOL_GPL(register_kprobe);
1225 1231