]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
riscv: ftrace: Properly acquire text_mutex to fix a race condition
authorAlexandre Ghiti <alexghiti@rivosinc.com>
Fri, 11 Jul 2025 07:38:38 +0000 (07:38 +0000)
committerPalmer Dabbelt <palmer@dabbelt.com>
Wed, 16 Jul 2025 15:21:47 +0000 (08:21 -0700)
As reported by lockdep, some patching was done without acquiring
text_mutex, so there could be a race when mapping the page to patch
since we use the same fixmap entry.

Reported-by: Han Gao <rabenda.cn@gmail.com>
Reported-by: Vivian Wang <wangruikang@iscas.ac.cn>
Reported-by: Yao Zi <ziyao@disroot.org>
Closes: https://lore.kernel.org/linux-riscv/aGODMpq7TGINddzM@pie.lan/
Tested-by: Yao Zi <ziyao@disroot.org>
Tested-by: Han Gao <rabenda.cn@gmail.com>
Reviewed-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
Signed-off-by: Alexandre Ghiti <alexghiti@rivosinc.com>
Link: https://lore.kernel.org/r/20250711-alex-fixes-v2-1-d85a5438da6c@rivosinc.com
Signed-off-by: Palmer Dabbelt <palmer@dabbelt.com>
arch/riscv/kernel/ftrace.c

index 4c6c24380cfd9d6c51f0e4340cd674160b83a610..8d18d6727f0fc8fa17d8f651b9e3a00c779cec85 100644 (file)
 #include <asm/text-patching.h>
 
 #ifdef CONFIG_DYNAMIC_FTRACE
+void ftrace_arch_code_modify_prepare(void)
+       __acquires(&text_mutex)
+{
+       mutex_lock(&text_mutex);
+}
+
+void ftrace_arch_code_modify_post_process(void)
+       __releases(&text_mutex)
+{
+       mutex_unlock(&text_mutex);
+}
+
 unsigned long ftrace_call_adjust(unsigned long addr)
 {
        if (IS_ENABLED(CONFIG_DYNAMIC_FTRACE_WITH_CALL_OPS))
@@ -29,10 +41,8 @@ unsigned long arch_ftrace_get_symaddr(unsigned long fentry_ip)
 
 void arch_ftrace_update_code(int command)
 {
-       mutex_lock(&text_mutex);
        command |= FTRACE_MAY_SLEEP;
        ftrace_modify_all_code(command);
-       mutex_unlock(&text_mutex);
        flush_icache_all();
 }
 
@@ -149,6 +159,8 @@ int ftrace_init_nop(struct module *mod, struct dyn_ftrace *rec)
        unsigned int nops[2], offset;
        int ret;
 
+       guard(mutex)(&text_mutex);
+
        ret = ftrace_rec_set_nop_ops(rec);
        if (ret)
                return ret;
@@ -157,9 +169,7 @@ int ftrace_init_nop(struct module *mod, struct dyn_ftrace *rec)
        nops[0] = to_auipc_t0(offset);
        nops[1] = RISCV_INSN_NOP4;
 
-       mutex_lock(&text_mutex);
        ret = patch_insn_write((void *)pc, nops, 2 * MCOUNT_INSN_SIZE);
-       mutex_unlock(&text_mutex);
 
        return ret;
 }