aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/kprobes.c
diff options
context:
space:
mode:
authorSteven Rostedt <srostedt@redhat.com>2010-10-18 10:38:58 -0400
committerSteven Rostedt <rostedt@goodmis.org>2010-10-29 12:55:55 -0400
commitde31c3ca8179d7c21def7ecb56e4fec0c8659d36 (patch)
tree63a488e1e3778c328074aaa47cb062b910d9c902 /kernel/kprobes.c
parent91bad2f8d3057482b9afb599f14421b007136960 (diff)
jump label: Fix error with preempt disable holding mutex
Kprobes and jump label were having a race between mutexes that was fixed by reordering the jump label. But this reordering moved the jump label mutex into a preempt disable location. This patch does a little fiddling to move the grabbing of the jump label mutex from inside the preempt disable section and still keep the order correct between the mutex and the kprobes lock. Reported-by: Ingo Molnar <mingo@elte.hu> Acked-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com> Cc: Jason Baron <jbaron@redhat.com> Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Diffstat (limited to 'kernel/kprobes.c')
-rw-r--r--kernel/kprobes.c26
1 files changed, 13 insertions, 13 deletions
diff --git a/kernel/kprobes.c b/kernel/kprobes.c
index 9437e14f36bd..9737a76e106f 100644
--- a/kernel/kprobes.c
+++ b/kernel/kprobes.c
@@ -1145,17 +1145,13 @@ int __kprobes register_kprobe(struct kprobe *p)
1145 if (ret) 1145 if (ret)
1146 return ret; 1146 return ret;
1147 1147
1148 preempt_disable();
1149 jump_label_lock(); 1148 jump_label_lock();
1149 preempt_disable();
1150 if (!kernel_text_address((unsigned long) p->addr) || 1150 if (!kernel_text_address((unsigned long) p->addr) ||
1151 in_kprobes_functions((unsigned long) p->addr) || 1151 in_kprobes_functions((unsigned long) p->addr) ||
1152 ftrace_text_reserved(p->addr, p->addr) || 1152 ftrace_text_reserved(p->addr, p->addr) ||
1153 jump_label_text_reserved(p->addr, p->addr)) { 1153 jump_label_text_reserved(p->addr, p->addr))
1154 preempt_enable(); 1154 goto fail_with_jump_label;
1155 jump_label_unlock();
1156 return -EINVAL;
1157 }
1158 jump_label_unlock();
1159 1155
1160 /* User can pass only KPROBE_FLAG_DISABLED to register_kprobe */ 1156 /* User can pass only KPROBE_FLAG_DISABLED to register_kprobe */
1161 p->flags &= KPROBE_FLAG_DISABLED; 1157 p->flags &= KPROBE_FLAG_DISABLED;
@@ -1169,10 +1165,9 @@ int __kprobes register_kprobe(struct kprobe *p)
1169 * We must hold a refcount of the probed module while updating 1165 * We must hold a refcount of the probed module while updating
1170 * its code to prohibit unexpected unloading. 1166 * its code to prohibit unexpected unloading.
1171 */ 1167 */
1172 if (unlikely(!try_module_get(probed_mod))) { 1168 if (unlikely(!try_module_get(probed_mod)))
1173 preempt_enable(); 1169 goto fail_with_jump_label;
1174 return -EINVAL; 1170
1175 }
1176 /* 1171 /*
1177 * If the module freed .init.text, we couldn't insert 1172 * If the module freed .init.text, we couldn't insert
1178 * kprobes in there. 1173 * kprobes in there.
@@ -1180,11 +1175,11 @@ int __kprobes register_kprobe(struct kprobe *p)
1180 if (within_module_init((unsigned long)p->addr, probed_mod) && 1175 if (within_module_init((unsigned long)p->addr, probed_mod) &&
1181 probed_mod->state != MODULE_STATE_COMING) { 1176 probed_mod->state != MODULE_STATE_COMING) {
1182 module_put(probed_mod); 1177 module_put(probed_mod);
1183 preempt_enable(); 1178 goto fail_with_jump_label;
1184 return -EINVAL;
1185 } 1179 }
1186 } 1180 }
1187 preempt_enable(); 1181 preempt_enable();
1182 jump_label_unlock();
1188 1183
1189 p->nmissed = 0; 1184 p->nmissed = 0;
1190 INIT_LIST_HEAD(&p->list); 1185 INIT_LIST_HEAD(&p->list);
@@ -1226,6 +1221,11 @@ out:
1226 module_put(probed_mod); 1221 module_put(probed_mod);
1227 1222
1228 return ret; 1223 return ret;
1224
1225fail_with_jump_label:
1226 preempt_enable();
1227 jump_label_unlock();
1228 return -EINVAL;
1229} 1229}
1230EXPORT_SYMBOL_GPL(register_kprobe); 1230EXPORT_SYMBOL_GPL(register_kprobe);
1231 1231