Skip to content

Commit 9f255b6

Browse files
jpoimboerostedt
authored andcommitted
module: Fix livepatch/ftrace module text permissions race
It's possible for livepatch and ftrace to be toggling a module's text permissions at the same time, resulting in the following panic: BUG: unable to handle page fault for address: ffffffffc005b1d9 #PF: supervisor write access in kernel mode #PF: error_code(0x0003) - permissions violation PGD 3ea0c067 P4D 3ea0c067 PUD 3ea0e067 PMD 3cc13067 PTE 3b8a1061 Oops: 0003 [#1] PREEMPT SMP PTI CPU: 1 PID: 453 Comm: insmod Tainted: G O K 5.2.0-rc1-a188339ca5 #1 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.12.0-20181126_142135-anatol 04/01/2014 RIP: 0010:apply_relocate_add+0xbe/0x14c Code: fa 0b 74 21 48 83 fa 18 74 38 48 83 fa 0a 75 40 eb 08 48 83 38 00 74 33 eb 53 83 38 00 75 4e 89 08 89 c8 eb 0a 83 38 00 75 43 <89> 08 48 63 c1 48 39 c8 74 2e eb 48 83 38 00 75 32 48 29 c1 89 08 RSP: 0018:ffffb223c00dbb10 EFLAGS: 00010246 RAX: ffffffffc005b1d9 RBX: 0000000000000000 RCX: ffffffff8b200060 RDX: 000000000000000b RSI: 0000004b0000000b RDI: ffff96bdfcd33000 RBP: ffffb223c00dbb38 R08: ffffffffc005d040 R09: ffffffffc005c1f0 R10: ffff96bdfcd33c40 R11: ffff96bdfcd33b80 R12: 0000000000000018 R13: ffffffffc005c1f0 R14: ffffffffc005e708 R15: ffffffff8b2fbc74 FS: 00007f5f447beba8(0000) GS:ffff96bdff900000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: ffffffffc005b1d9 CR3: 000000003cedc002 CR4: 0000000000360ea0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 Call Trace: klp_init_object_loaded+0x10f/0x219 ? preempt_latency_start+0x21/0x57 klp_enable_patch+0x662/0x809 ? virt_to_head_page+0x3a/0x3c ? kfree+0x8c/0x126 patch_init+0x2ed/0x1000 [livepatch_test02] ? 0xffffffffc0060000 do_one_initcall+0x9f/0x1c5 ? kmem_cache_alloc_trace+0xc4/0xd4 ? do_init_module+0x27/0x210 do_init_module+0x5f/0x210 load_module+0x1c41/0x2290 ? fsnotify_path+0x3b/0x42 ? strstarts+0x2b/0x2b ? kernel_read+0x58/0x65 __do_sys_finit_module+0x9f/0xc3 ? __do_sys_finit_module+0x9f/0xc3 __x64_sys_finit_module+0x1a/0x1c do_syscall_64+0x52/0x61 entry_SYSCALL_64_after_hwframe+0x44/0xa9 The above panic occurs when loading two modules at the same time with ftrace enabled, where at least one of the modules is a livepatch module: CPU0 CPU1 klp_enable_patch() klp_init_object_loaded() module_disable_ro() ftrace_module_enable() ftrace_arch_code_modify_post_process() set_all_modules_text_ro() klp_write_object_relocations() apply_relocate_add() *patches read-only code* - BOOM A similar race exists when toggling ftrace while loading a livepatch module. Fix it by ensuring that the livepatch and ftrace code patching operations -- and their respective permissions changes -- are protected by the text_mutex. Link: http://lkml.kernel.org/r/ab43d56ab909469ac5d2520c5d944ad6d4abd476.1560474114.git.jpoimboe@redhat.com Reported-by: Johannes Erdfelt <[email protected]> Fixes: 444d13f ("modules: add ro_after_init support") Acked-by: Jessica Yu <[email protected]> Reviewed-by: Petr Mladek <[email protected]> Reviewed-by: Miroslav Benes <[email protected]> Signed-off-by: Josh Poimboeuf <[email protected]> Signed-off-by: Steven Rostedt (VMware) <[email protected]>
1 parent a415834 commit 9f255b6

File tree

2 files changed

+15
-1
lines changed

2 files changed

+15
-1
lines changed

kernel/livepatch/core.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#include <linux/elf.h>
3131
#include <linux/moduleloader.h>
3232
#include <linux/completion.h>
33+
#include <linux/memory.h>
3334
#include <asm/cacheflush.h>
3435
#include "core.h"
3536
#include "patch.h"
@@ -730,16 +731,21 @@ static int klp_init_object_loaded(struct klp_patch *patch,
730731
struct klp_func *func;
731732
int ret;
732733

734+
mutex_lock(&text_mutex);
735+
733736
module_disable_ro(patch->mod);
734737
ret = klp_write_object_relocations(patch->mod, obj);
735738
if (ret) {
736739
module_enable_ro(patch->mod, true);
740+
mutex_unlock(&text_mutex);
737741
return ret;
738742
}
739743

740744
arch_klp_init_object_loaded(patch, obj);
741745
module_enable_ro(patch->mod, true);
742746

747+
mutex_unlock(&text_mutex);
748+
743749
klp_for_each_func(obj, func) {
744750
ret = klp_find_object_symbol(obj->name, func->old_name,
745751
func->old_sympos,

kernel/trace/ftrace.c

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
#include <linux/hash.h>
3535
#include <linux/rcupdate.h>
3636
#include <linux/kprobes.h>
37+
#include <linux/memory.h>
3738

3839
#include <trace/events/sched.h>
3940

@@ -2610,10 +2611,12 @@ static void ftrace_run_update_code(int command)
26102611
{
26112612
int ret;
26122613

2614+
mutex_lock(&text_mutex);
2615+
26132616
ret = ftrace_arch_code_modify_prepare();
26142617
FTRACE_WARN_ON(ret);
26152618
if (ret)
2616-
return;
2619+
goto out_unlock;
26172620

26182621
/*
26192622
* By default we use stop_machine() to modify the code.
@@ -2625,6 +2628,9 @@ static void ftrace_run_update_code(int command)
26252628

26262629
ret = ftrace_arch_code_modify_post_process();
26272630
FTRACE_WARN_ON(ret);
2631+
2632+
out_unlock:
2633+
mutex_unlock(&text_mutex);
26282634
}
26292635

26302636
static void ftrace_run_modify_code(struct ftrace_ops *ops, int command,
@@ -5775,6 +5781,7 @@ void ftrace_module_enable(struct module *mod)
57755781
struct ftrace_page *pg;
57765782

57775783
mutex_lock(&ftrace_lock);
5784+
mutex_lock(&text_mutex);
57785785

57795786
if (ftrace_disabled)
57805787
goto out_unlock;
@@ -5836,6 +5843,7 @@ void ftrace_module_enable(struct module *mod)
58365843
ftrace_arch_code_modify_post_process();
58375844

58385845
out_unlock:
5846+
mutex_unlock(&text_mutex);
58395847
mutex_unlock(&ftrace_lock);
58405848

58415849
process_cached_mods(mod->name);

0 commit comments

Comments
 (0)