Skip to content

Commit e846d13

Browse files
zhouchengming1Ingo Molnar
authored andcommitted
kprobes, x86/alternatives: Use text_mutex to protect smp_alt_modules
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@huawei.com> Reviewed-by: Masami Hiramatsu <mhiramat@kernel.org> Acked-by: Steven Rostedt (VMware) <rostedt@goodmis.org> Cc: Andy Lutomirski <luto@kernel.org> Cc: Borislav Petkov <bp@alien8.de> Cc: Brian Gerst <brgerst@gmail.com> Cc: Denys Vlasenko <dvlasenk@redhat.com> Cc: H. Peter Anvin <hpa@zytor.com> Cc: Josh Poimboeuf <jpoimboe@redhat.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: bp@suse.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@kernel.org>
1 parent d786f05 commit e846d13

File tree

2 files changed

+15
-13
lines changed

2 files changed

+15
-13
lines changed

arch/x86/kernel/alternative.c

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -442,7 +442,6 @@ static void alternatives_smp_lock(const s32 *start, const s32 *end,
442442
{
443443
const s32 *poff;
444444

445-
mutex_lock(&text_mutex);
446445
for (poff = start; poff < end; poff++) {
447446
u8 *ptr = (u8 *)poff + *poff;
448447

@@ -452,15 +451,13 @@ static void alternatives_smp_lock(const s32 *start, const s32 *end,
452451
if (*ptr == 0x3e)
453452
text_poke(ptr, ((unsigned char []){0xf0}), 1);
454453
}
455-
mutex_unlock(&text_mutex);
456454
}
457455

458456
static void alternatives_smp_unlock(const s32 *start, const s32 *end,
459457
u8 *text, u8 *text_end)
460458
{
461459
const s32 *poff;
462460

463-
mutex_lock(&text_mutex);
464461
for (poff = start; poff < end; poff++) {
465462
u8 *ptr = (u8 *)poff + *poff;
466463

@@ -470,7 +467,6 @@ static void alternatives_smp_unlock(const s32 *start, const s32 *end,
470467
if (*ptr == 0xf0)
471468
text_poke(ptr, ((unsigned char []){0x3E}), 1);
472469
}
473-
mutex_unlock(&text_mutex);
474470
}
475471

476472
struct smp_alt_module {
@@ -489,8 +485,7 @@ struct smp_alt_module {
489485
struct list_head next;
490486
};
491487
static LIST_HEAD(smp_alt_modules);
492-
static DEFINE_MUTEX(smp_alt);
493-
static bool uniproc_patched = false; /* protected by smp_alt */
488+
static bool uniproc_patched = false; /* protected by text_mutex */
494489

495490
void __init_or_module alternatives_smp_module_add(struct module *mod,
496491
char *name,
@@ -499,7 +494,7 @@ void __init_or_module alternatives_smp_module_add(struct module *mod,
499494
{
500495
struct smp_alt_module *smp;
501496

502-
mutex_lock(&smp_alt);
497+
mutex_lock(&text_mutex);
503498
if (!uniproc_patched)
504499
goto unlock;
505500

@@ -526,22 +521,22 @@ void __init_or_module alternatives_smp_module_add(struct module *mod,
526521
smp_unlock:
527522
alternatives_smp_unlock(locks, locks_end, text, text_end);
528523
unlock:
529-
mutex_unlock(&smp_alt);
524+
mutex_unlock(&text_mutex);
530525
}
531526

532527
void __init_or_module alternatives_smp_module_del(struct module *mod)
533528
{
534529
struct smp_alt_module *item;
535530

536-
mutex_lock(&smp_alt);
531+
mutex_lock(&text_mutex);
537532
list_for_each_entry(item, &smp_alt_modules, next) {
538533
if (mod != item->mod)
539534
continue;
540535
list_del(&item->next);
541536
kfree(item);
542537
break;
543538
}
544-
mutex_unlock(&smp_alt);
539+
mutex_unlock(&text_mutex);
545540
}
546541

547542
void alternatives_enable_smp(void)
@@ -551,7 +546,7 @@ void alternatives_enable_smp(void)
551546
/* Why bother if there are no other CPUs? */
552547
BUG_ON(num_possible_cpus() == 1);
553548

554-
mutex_lock(&smp_alt);
549+
mutex_lock(&text_mutex);
555550

556551
if (uniproc_patched) {
557552
pr_info("switching to SMP code\n");
@@ -563,17 +558,22 @@ void alternatives_enable_smp(void)
563558
mod->text, mod->text_end);
564559
uniproc_patched = false;
565560
}
566-
mutex_unlock(&smp_alt);
561+
mutex_unlock(&text_mutex);
567562
}
568563

569-
/* Return 1 if the address range is reserved for smp-alternatives */
564+
/*
565+
* Return 1 if the address range is reserved for SMP-alternatives.
566+
* Must hold text_mutex.
567+
*/
570568
int alternatives_text_reserved(void *start, void *end)
571569
{
572570
struct smp_alt_module *mod;
573571
const s32 *poff;
574572
u8 *text_start = start;
575573
u8 *text_end = end;
576574

575+
lockdep_assert_held(&text_mutex);
576+
577577
list_for_each_entry(mod, &smp_alt_modules, next) {
578578
if (mod->text > text_end || mod->text_end < text_start)
579579
continue;

kernel/extable.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@
3131
* mutex protecting text section modification (dynamic code patching).
3232
* some users need to sleep (allocating memory...) while they hold this lock.
3333
*
34+
* Note: Also protects SMP-alternatives modification on x86.
35+
*
3436
* NOT exported to modules - patching kernel text is a really delicate matter.
3537
*/
3638
DEFINE_MUTEX(text_mutex);

0 commit comments

Comments
 (0)