Skip to content

Commit e3f16d6

Browse files
Alexandre Ghitipalmer-dabbelt
authored andcommitted
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 <[email protected]> Reported-by: Vivian Wang <[email protected]> Reported-by: Yao Zi <[email protected]> Closes: https://lore.kernel.org/linux-riscv/[email protected]/ Tested-by: Yao Zi <[email protected]> Tested-by: Han Gao <[email protected]> Reviewed-by: Masami Hiramatsu (Google) <[email protected]> Signed-off-by: Alexandre Ghiti <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Palmer Dabbelt <[email protected]>
1 parent 16d7436 commit e3f16d6

File tree

1 file changed

+14
-4
lines changed

1 file changed

+14
-4
lines changed

arch/riscv/kernel/ftrace.c

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,18 @@
1414
#include <asm/text-patching.h>
1515

1616
#ifdef CONFIG_DYNAMIC_FTRACE
17+
void ftrace_arch_code_modify_prepare(void)
18+
__acquires(&text_mutex)
19+
{
20+
mutex_lock(&text_mutex);
21+
}
22+
23+
void ftrace_arch_code_modify_post_process(void)
24+
__releases(&text_mutex)
25+
{
26+
mutex_unlock(&text_mutex);
27+
}
28+
1729
unsigned long ftrace_call_adjust(unsigned long addr)
1830
{
1931
if (IS_ENABLED(CONFIG_DYNAMIC_FTRACE_WITH_CALL_OPS))
@@ -29,10 +41,8 @@ unsigned long arch_ftrace_get_symaddr(unsigned long fentry_ip)
2941

3042
void arch_ftrace_update_code(int command)
3143
{
32-
mutex_lock(&text_mutex);
3344
command |= FTRACE_MAY_SLEEP;
3445
ftrace_modify_all_code(command);
35-
mutex_unlock(&text_mutex);
3646
flush_icache_all();
3747
}
3848

@@ -149,6 +159,8 @@ int ftrace_init_nop(struct module *mod, struct dyn_ftrace *rec)
149159
unsigned int nops[2], offset;
150160
int ret;
151161

162+
guard(mutex)(&text_mutex);
163+
152164
ret = ftrace_rec_set_nop_ops(rec);
153165
if (ret)
154166
return ret;
@@ -157,9 +169,7 @@ int ftrace_init_nop(struct module *mod, struct dyn_ftrace *rec)
157169
nops[0] = to_auipc_t0(offset);
158170
nops[1] = RISCV_INSN_NOP4;
159171

160-
mutex_lock(&text_mutex);
161172
ret = patch_insn_write((void *)pc, nops, 2 * MCOUNT_INSN_SIZE);
162-
mutex_unlock(&text_mutex);
163173

164174
return ret;
165175
}

0 commit comments

Comments
 (0)