All of lore.kernel.org
 help / color / mirror / Atom feed
From: Steven Rostedt <rostedt@goodmis.org>
To: linux-kernel@vger.kernel.org
Cc: Ingo Molnar <mingo@elte.hu>,
	Andrew Morton <akpm@linux-foundation.org>,
	Frederic Weisbecker <fweisbec@gmail.com>,
	Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>,
	Jason Baron <jbaron@redhat.com>
Subject: [PATCH 4/9] jump label: Fix deadlock b/w jump_label_mutex vs. text_mutex
Date: Fri, 15 Oct 2010 16:09:53 -0400	[thread overview]
Message-ID: <20101015201036.691801067@goodmis.org> (raw)
In-Reply-To: 20101015200949.134732894@goodmis.org

[-- Attachment #1: 0004-jump-label-Fix-deadlock-b-w-jump_label_mutex-vs.-tex.patch --]
[-- Type: text/plain, Size: 5916 bytes --]

From: Jason Baron <jbaron@redhat.com>

register_kprobe() downs the 'text_mutex' and then calls
jump_label_text_reserved(), which downs the 'jump_label_mutex'.
However, the jump label code takes those mutexes in the reverse
order.

Fix by requiring the caller of jump_label_text_reserved() to do
the jump label locking via the newly added: jump_label_lock(),
jump_label_unlock(). Currently, kprobes is the only user
of jump_label_text_reserved().

Reported-by: Ingo Molnar <mingo@elte.hu>
Acked-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Signed-off-by: Jason Baron <jbaron@redhat.com>
LKML-Reference: <759032c48d5e30c27f0bba003d09bffa8e9f28bb.1285965957.git.jbaron@redhat.com>
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
---
 include/linux/jump_label.h |    5 +++++
 kernel/jump_label.c        |   33 +++++++++++++++++++++------------
 kernel/kprobes.c           |    6 ++++++
 3 files changed, 32 insertions(+), 12 deletions(-)

diff --git a/include/linux/jump_label.h b/include/linux/jump_label.h
index b72cd9f..cf213d1 100644
--- a/include/linux/jump_label.h
+++ b/include/linux/jump_label.h
@@ -18,6 +18,8 @@ struct module;
 extern struct jump_entry __start___jump_table[];
 extern struct jump_entry __stop___jump_table[];
 
+extern void jump_label_lock(void);
+extern void jump_label_unlock(void);
 extern void arch_jump_label_transform(struct jump_entry *entry,
 				 enum jump_label_type type);
 extern void arch_jump_label_text_poke_early(jump_label_t addr);
@@ -59,6 +61,9 @@ static inline int jump_label_text_reserved(void *start, void *end)
 	return 0;
 }
 
+static inline void jump_label_lock(void) {}
+static inline void jump_label_unlock(void) {}
+
 #endif
 
 #endif
diff --git a/kernel/jump_label.c b/kernel/jump_label.c
index be9e105..12cce78 100644
--- a/kernel/jump_label.c
+++ b/kernel/jump_label.c
@@ -39,6 +39,16 @@ struct jump_label_module_entry {
 	struct module *mod;
 };
 
+void jump_label_lock(void)
+{
+	mutex_lock(&jump_label_mutex);
+}
+
+void jump_label_unlock(void)
+{
+	mutex_unlock(&jump_label_mutex);
+}
+
 static int jump_label_cmp(const void *a, const void *b)
 {
 	const struct jump_entry *jea = a;
@@ -152,7 +162,7 @@ void jump_label_update(unsigned long key, enum jump_label_type type)
 	struct jump_label_module_entry *e_module;
 	int count;
 
-	mutex_lock(&jump_label_mutex);
+	jump_label_lock();
 	entry = get_jump_label_entry((jump_label_t)key);
 	if (entry) {
 		count = entry->nr_entries;
@@ -175,7 +185,7 @@ void jump_label_update(unsigned long key, enum jump_label_type type)
 			}
 		}
 	}
-	mutex_unlock(&jump_label_mutex);
+	jump_label_unlock();
 }
 
 static int addr_conflict(struct jump_entry *entry, void *start, void *end)
@@ -232,6 +242,7 @@ out:
  * overlaps with any of the jump label patch addresses. Code
  * that wants to modify kernel text should first verify that
  * it does not overlap with any of the jump label addresses.
+ * Caller must hold jump_label_mutex.
  *
  * returns 1 if there is an overlap, 0 otherwise
  */
@@ -242,7 +253,6 @@ int jump_label_text_reserved(void *start, void *end)
 	struct jump_entry *iter_stop = __start___jump_table;
 	int conflict = 0;
 
-	mutex_lock(&jump_label_mutex);
 	iter = iter_start;
 	while (iter < iter_stop) {
 		if (addr_conflict(iter, start, end)) {
@@ -257,7 +267,6 @@ int jump_label_text_reserved(void *start, void *end)
 	conflict = module_conflict(start, end);
 #endif
 out:
-	mutex_unlock(&jump_label_mutex);
 	return conflict;
 }
 
@@ -268,7 +277,7 @@ static __init int init_jump_label(void)
 	struct jump_entry *iter_stop = __stop___jump_table;
 	struct jump_entry *iter;
 
-	mutex_lock(&jump_label_mutex);
+	jump_label_lock();
 	ret = build_jump_label_hashtable(__start___jump_table,
 					 __stop___jump_table);
 	iter = iter_start;
@@ -276,7 +285,7 @@ static __init int init_jump_label(void)
 		arch_jump_label_text_poke_early(iter->code);
 		iter++;
 	}
-	mutex_unlock(&jump_label_mutex);
+	jump_label_unlock();
 	return ret;
 }
 early_initcall(init_jump_label);
@@ -409,21 +418,21 @@ jump_label_module_notify(struct notifier_block *self, unsigned long val,
 
 	switch (val) {
 	case MODULE_STATE_COMING:
-		mutex_lock(&jump_label_mutex);
+		jump_label_lock();
 		ret = add_jump_label_module(mod);
 		if (ret)
 			remove_jump_label_module(mod);
-		mutex_unlock(&jump_label_mutex);
+		jump_label_unlock();
 		break;
 	case MODULE_STATE_GOING:
-		mutex_lock(&jump_label_mutex);
+		jump_label_lock();
 		remove_jump_label_module(mod);
-		mutex_unlock(&jump_label_mutex);
+		jump_label_unlock();
 		break;
 	case MODULE_STATE_LIVE:
-		mutex_lock(&jump_label_mutex);
+		jump_label_lock();
 		remove_jump_label_module_init(mod);
-		mutex_unlock(&jump_label_mutex);
+		jump_label_unlock();
 		break;
 	}
 	return ret;
diff --git a/kernel/kprobes.c b/kernel/kprobes.c
index ec4210c..d45d72e 100644
--- a/kernel/kprobes.c
+++ b/kernel/kprobes.c
@@ -1145,13 +1145,16 @@ int __kprobes register_kprobe(struct kprobe *p)
 		return ret;
 
 	preempt_disable();
+	jump_label_lock();
 	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();
 
 	/* User can pass only KPROBE_FLAG_DISABLED to register_kprobe */
 	p->flags &= KPROBE_FLAG_DISABLED;
@@ -1186,6 +1189,8 @@ int __kprobes register_kprobe(struct kprobe *p)
 	INIT_LIST_HEAD(&p->list);
 	mutex_lock(&kprobe_mutex);
 
+	jump_label_lock(); /* needed to call jump_label_text_reserved() */
+
 	get_online_cpus();	/* For avoiding text_mutex deadlock. */
 	mutex_lock(&text_mutex);
 
@@ -1213,6 +1218,7 @@ int __kprobes register_kprobe(struct kprobe *p)
 out:
 	mutex_unlock(&text_mutex);
 	put_online_cpus();
+	jump_label_unlock();
 	mutex_unlock(&kprobe_mutex);
 
 	if (probed_mod)
-- 
1.7.1



  parent reply	other threads:[~2010-10-15 20:12 UTC|newest]

Thread overview: 40+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2010-10-15 20:09 [PATCH 0/9] [GIT PULL] jump label: various updates Steven Rostedt
2010-10-15 20:09 ` [PATCH 1/9] jump label/x86: Move arch_init_ideal_nop5 later Steven Rostedt
2010-10-15 20:09 ` [PATCH 2/9] tracing/x86: No need to disable interrupts when calling arch_init_ideal_nop5 Steven Rostedt
2010-10-15 20:09 ` [PATCH 3/9] jump label: Fix module __init section race Steven Rostedt
2010-10-16  2:09   ` Steven Rostedt
2010-10-16  6:23     ` Ingo Molnar
2010-10-16 16:23       ` Steven Rostedt
2010-10-18 14:14         ` Jason Baron
2010-10-15 20:09 ` Steven Rostedt [this message]
2010-10-15 20:55   ` [PATCH 4/9] jump label: Fix deadlock b/w jump_label_mutex vs. text_mutex Peter Zijlstra
2010-10-16  2:16     ` Steven Rostedt
2010-10-16  2:25     ` Steven Rostedt
2010-10-16  4:21       ` Steven Rostedt
2010-10-15 20:09 ` [PATCH 5/9] jump label: Add register_jump_label_key/unregister_jump_label_key Steven Rostedt
2010-10-15 20:58   ` Peter Zijlstra
2010-10-16  2:11     ` Steven Rostedt
2010-10-15 21:03   ` Peter Zijlstra
2010-10-15 21:09     ` Steven Rostedt
2010-10-15 21:13       ` Peter Zijlstra
2010-10-18 12:05         ` Peter Zijlstra
2010-10-18 14:03           ` Jason Baron
2010-10-18 14:07             ` Peter Zijlstra
2010-10-15 20:09 ` [PATCH 6/9] jump label: Move jump table to r/w section Steven Rostedt
2010-10-15 20:09 ` [PATCH 7/9] jump label: Add docs Steven Rostedt
2010-10-15 20:09 ` [PATCH 8/9] jump label: Make arch_jump_label_text_poke_early() optional Steven Rostedt
2010-10-15 21:06   ` Peter Zijlstra
2010-10-15 21:08     ` Steven Rostedt
2010-10-15 21:22       ` David Daney
2010-10-15 21:35         ` Steven Rostedt
2010-10-15 21:38           ` David Daney
2010-10-16  1:08             ` Steven Rostedt
2010-10-30 10:40   ` [tip:perf/urgent] " tip-bot for Steven Rostedt
2010-10-15 20:09 ` [PATCH 9/9] jump label: Add MIPS support Steven Rostedt
2010-10-15 20:17 ` [PATCH 0/9] [GIT PULL] jump label: various updates Steven Rostedt
2010-10-16  1:10 ` Steven Rostedt
  -- strict thread matches above, loose matches on Subject: below --
2010-10-04 18:56 [PATCH v2 0/2] jump label: Add MIPS architecture support David Daney
2010-10-04 18:56 ` [PATCH v2 1/2] jump label: Make arch_jump_label_text_poke_early() optional David Daney
2010-10-04 18:56 ` [PATCH v2 2/2] jump label: Add MIPS support David Daney
2010-10-06 23:00   ` Ralf Baechle
2010-10-07  1:26     ` David Daney

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20101015201036.691801067@goodmis.org \
    --to=rostedt@goodmis.org \
    --cc=akpm@linux-foundation.org \
    --cc=fweisbec@gmail.com \
    --cc=jbaron@redhat.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=masami.hiramatsu.pt@hitachi.com \
    --cc=mingo@elte.hu \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.