[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <lsq.1518322806.661963316@decadent.org.uk>
Date: Sun, 11 Feb 2018 04:20:06 +0000
From: Ben Hutchings <ben@...adent.org.uk>
To: linux-kernel@...r.kernel.org, stable@...r.kernel.org
CC: akpm@...ux-foundation.org, "Ingo Molnar" <mingo@...nel.org>,
"Peter Zijlstra" <peterz@...radead.org>, bp@...e.de,
"Josh Poimboeuf" <jpoimboe@...hat.com>,
"Thomas Gleixner" <tglx@...utronix.de>,
"Linus Torvalds" <torvalds@...ux-foundation.org>,
"Andy Lutomirski" <luto@...nel.org>,
"Brian Gerst" <brgerst@...il.com>,
"Denys Vlasenko" <dvlasenk@...hat.com>,
"Zhou Chengming" <zhouchengming1@...wei.com>,
"Steven Rostedt (VMware)" <rostedt@...dmis.org>,
"Borislav Petkov" <bp@...en8.de>, "H. Peter Anvin" <hpa@...or.com>,
"Masami Hiramatsu" <mhiramat@...nel.org>
Subject: [PATCH 3.2 30/79] kprobes, x86/alternatives: Use text_mutex to
protect smp_alt_modules
3.2.99-rc1 review patch. If anyone has any objections, please let me know.
------------------
From: Zhou Chengming <zhouchengming1@...wei.com>
commit e846d13958066828a9483d862cc8370a72fadbb6 upstream.
We use alternatives_text_reserved() to check if the address is in
the fixed pieces of alternative reserved, but the problem is that
we don't hold the smp_alt mutex when call this function. So the list
traversal may encounter a deleted list_head if another path is doing
alternatives_smp_module_del().
One solution is that we can hold smp_alt mutex before call this
function, but the difficult point is that the callers of this
functions, arch_prepare_kprobe() and arch_prepare_optimized_kprobe(),
are called inside the text_mutex. So we must hold smp_alt mutex
before we go into these arch dependent code. But we can't now,
the smp_alt mutex is the arch dependent part, only x86 has it.
Maybe we can export another arch dependent callback to solve this.
But there is a simpler way to handle this problem. We can reuse the
text_mutex to protect smp_alt_modules instead of using another mutex.
And all the arch dependent checks of kprobes are inside the text_mutex,
so it's safe now.
Signed-off-by: Zhou Chengming <zhouchengming1@...wei.com>
Reviewed-by: Masami Hiramatsu <mhiramat@...nel.org>
Acked-by: Steven Rostedt (VMware) <rostedt@...dmis.org>
Cc: Andy Lutomirski <luto@...nel.org>
Cc: Borislav Petkov <bp@...en8.de>
Cc: Brian Gerst <brgerst@...il.com>
Cc: Denys Vlasenko <dvlasenk@...hat.com>
Cc: H. Peter Anvin <hpa@...or.com>
Cc: Josh Poimboeuf <jpoimboe@...hat.com>
Cc: Linus Torvalds <torvalds@...ux-foundation.org>
Cc: Peter Zijlstra <peterz@...radead.org>
Cc: Thomas Gleixner <tglx@...utronix.de>
Cc: bp@...e.de
Fixes: 2cfa197 "ftrace/alternatives: Introducing *_text_reserved functions"
Link: http://lkml.kernel.org/r/1509585501-79466-1-git-send-email-zhouchengming1@huawei.com
Signed-off-by: Ingo Molnar <mingo@...nel.org>
[bwh: Backported to 3.2: adjust context]
Signed-off-by: Ben Hutchings <ben@...adent.org.uk>
---
arch/x86/kernel/alternative.c | 26 +++++++++++++-------------
kernel/extable.c | 2 ++
2 files changed, 15 insertions(+), 13 deletions(-)
--- a/arch/x86/kernel/alternative.c
+++ b/arch/x86/kernel/alternative.c
@@ -407,7 +407,6 @@ static void alternatives_smp_lock(const
{
const s32 *poff;
- mutex_lock(&text_mutex);
for (poff = start; poff < end; poff++) {
u8 *ptr = (u8 *)poff + *poff;
@@ -417,7 +416,6 @@ static void alternatives_smp_lock(const
if (*ptr == 0x3e)
text_poke(ptr, ((unsigned char []){0xf0}), 1);
};
- mutex_unlock(&text_mutex);
}
static void alternatives_smp_unlock(const s32 *start, const s32 *end,
@@ -425,7 +423,6 @@ static void alternatives_smp_unlock(cons
{
const s32 *poff;
- mutex_lock(&text_mutex);
for (poff = start; poff < end; poff++) {
u8 *ptr = (u8 *)poff + *poff;
@@ -435,7 +432,6 @@ static void alternatives_smp_unlock(cons
if (*ptr == 0xf0)
text_poke(ptr, ((unsigned char []){0x3E}), 1);
};
- mutex_unlock(&text_mutex);
}
struct smp_alt_module {
@@ -454,8 +450,7 @@ struct smp_alt_module {
struct list_head next;
};
static LIST_HEAD(smp_alt_modules);
-static DEFINE_MUTEX(smp_alt);
-static bool uniproc_patched = false; /* protected by smp_alt */
+static bool uniproc_patched = false; /* protected by text_mutex */
void __init_or_module alternatives_smp_module_add(struct module *mod,
char *name,
@@ -464,7 +459,7 @@ void __init_or_module alternatives_smp_m
{
struct smp_alt_module *smp;
- mutex_lock(&smp_alt);
+ mutex_lock(&text_mutex);
if (!uniproc_patched)
goto unlock;
@@ -491,14 +486,14 @@ void __init_or_module alternatives_smp_m
smp_unlock:
alternatives_smp_unlock(locks, locks_end, text, text_end);
unlock:
- mutex_unlock(&smp_alt);
+ mutex_unlock(&text_mutex);
}
void __init_or_module alternatives_smp_module_del(struct module *mod)
{
struct smp_alt_module *item;
- mutex_lock(&smp_alt);
+ mutex_lock(&text_mutex);
list_for_each_entry(item, &smp_alt_modules, next) {
if (mod != item->mod)
continue;
@@ -506,7 +501,7 @@ void __init_or_module alternatives_smp_m
kfree(item);
break;
}
- mutex_unlock(&smp_alt);
+ mutex_unlock(&text_mutex);
}
void alternatives_enable_smp(void)
@@ -527,7 +522,7 @@ void alternatives_enable_smp(void)
/* Why bother if there are no other CPUs? */
BUG_ON(num_possible_cpus() == 1);
- mutex_lock(&smp_alt);
+ mutex_lock(&text_mutex);
if (uniproc_patched) {
printk(KERN_INFO "SMP alternatives: switching to SMP code\n");
@@ -539,10 +534,13 @@ void alternatives_enable_smp(void)
mod->text, mod->text_end);
uniproc_patched = false;
}
- mutex_unlock(&smp_alt);
+ mutex_unlock(&text_mutex);
}
-/* Return 1 if the address range is reserved for smp-alternatives */
+/*
+ * Return 1 if the address range is reserved for SMP-alternatives.
+ * Must hold text_mutex.
+ */
int alternatives_text_reserved(void *start, void *end)
{
struct smp_alt_module *mod;
@@ -550,6 +548,8 @@ int alternatives_text_reserved(void *sta
u8 *text_start = start;
u8 *text_end = end;
+ lockdep_assert_held(&text_mutex);
+
list_for_each_entry(mod, &smp_alt_modules, next) {
if (mod->text > text_end || mod->text_end < text_start)
continue;
--- a/kernel/extable.c
+++ b/kernel/extable.c
@@ -28,6 +28,8 @@
* mutex protecting text section modification (dynamic code patching).
* some users need to sleep (allocating memory...) while they hold this lock.
*
+ * Note: Also protects SMP-alternatives modification on x86.
+ *
* NOT exported to modules - patching kernel text is a really delicate matter.
*/
DEFINE_MUTEX(text_mutex);
Powered by blists - more mailing lists