Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit de31c3ca authored by Steven Rostedt's avatar Steven Rostedt Committed by Steven Rostedt
Browse files

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: default avatarIngo Molnar <mingo@elte.hu>
Acked-by: default avatarMasami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Cc: Jason Baron <jbaron@redhat.com>
Signed-off-by: default avatarSteven Rostedt <rostedt@goodmis.org>
parent 91bad2f8
Loading
Loading
Loading
Loading
+13 −13
Original line number Original line Diff line number Diff line
@@ -1145,17 +1145,13 @@ int __kprobes register_kprobe(struct kprobe *p)
	if (ret)
	if (ret)
		return ret;
		return ret;


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


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

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


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


	return ret;
	return ret;

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