From e3f16d63d54e6fcf2b18812f2dd0a8d2782b5f3a Mon Sep 17 00:00:00 2001 From: Alexandre Ghiti Date: Fri, 11 Jul 2025 07:38:38 +0000 Subject: [PATCH] riscv: ftrace: Properly acquire text_mutex to fix a race condition 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 Reported-by: Vivian Wang Reported-by: Yao Zi Closes: https://lore.kernel.org/linux-riscv/aGODMpq7TGINddzM@pie.lan/ Tested-by: Yao Zi Tested-by: Han Gao Reviewed-by: Masami Hiramatsu (Google) Signed-off-by: Alexandre Ghiti Link: https://lore.kernel.org/r/20250711-alex-fixes-v2-1-d85a5438da6c@rivosinc.com Signed-off-by: Palmer Dabbelt --- arch/riscv/kernel/ftrace.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/arch/riscv/kernel/ftrace.c b/arch/riscv/kernel/ftrace.c index 4c6c24380cfd..8d18d6727f0f 100644 --- a/arch/riscv/kernel/ftrace.c +++ b/arch/riscv/kernel/ftrace.c @@ -14,6 +14,18 @@ #include #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; } -- 2.25.1