Skip to content

Commit

Permalink
jump label: Fix error with preempt disable holding mutex
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Steven Rostedt authored and Steven Rostedt committed Oct 29, 2010
1 parent 91bad2f commit de31c3c
Showing 1 changed file with 13 additions and 13 deletions.
26 changes: 13 additions & 13 deletions kernel/kprobes.c
Original file line number Diff line number Diff line change
Expand Up @@ -1145,17 +1145,13 @@ int __kprobes register_kprobe(struct kprobe *p)
if (ret)
return ret;

preempt_disable();
jump_label_lock();
preempt_disable();
if (!kernel_text_address((unsigned long) p->addr) ||
in_kprobes_functions((unsigned long) p->addr) ||
ftrace_text_reserved(p->addr, p->addr) ||
jump_label_text_reserved(p->addr, p->addr)) {
preempt_enable();
jump_label_unlock();
return -EINVAL;
}
jump_label_unlock();
jump_label_text_reserved(p->addr, p->addr))
goto fail_with_jump_label;

/* User can pass only KPROBE_FLAG_DISABLED to register_kprobe */
p->flags &= KPROBE_FLAG_DISABLED;
Expand All @@ -1169,22 +1165,21 @@ int __kprobes register_kprobe(struct kprobe *p)
* We must hold a refcount of the probed module while updating
* its code to prohibit unexpected unloading.
*/
if (unlikely(!try_module_get(probed_mod))) {
preempt_enable();
return -EINVAL;
}
if (unlikely(!try_module_get(probed_mod)))
goto fail_with_jump_label;

/*
* If the module freed .init.text, we couldn't insert
* kprobes in there.
*/
if (within_module_init((unsigned long)p->addr, probed_mod) &&
probed_mod->state != MODULE_STATE_COMING) {
module_put(probed_mod);
preempt_enable();
return -EINVAL;
goto fail_with_jump_label;
}
}
preempt_enable();
jump_label_unlock();

p->nmissed = 0;
INIT_LIST_HEAD(&p->list);
Expand Down Expand Up @@ -1226,6 +1221,11 @@ int __kprobes register_kprobe(struct kprobe *p)
module_put(probed_mod);

return ret;

fail_with_jump_label:
preempt_enable();
jump_label_unlock();
return -EINVAL;
}
EXPORT_SYMBOL_GPL(register_kprobe);

Expand Down

0 comments on commit de31c3c

Please sign in to comment.