From: Sven Schnelle Date: Tue, 23 Jul 2019 20:37:54 +0000 (+0200) Subject: parisc: fix race condition in patching code X-Git-Tag: v5.3-rc3~19^2~3 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=740f05f30a8c49ec63668055d28feedd906d3c50;p=thirdparty%2Fkernel%2Flinux.git parisc: fix race condition in patching code Assume the following ftrace code sequence that was patched in earlier by ftrace_make_call(): PAGE A: ffc: addr of ftrace_caller() PAGE B: 000: 0x6fc10080 /* stw,ma r1,40(sp) */ 004: 0x48213fd1 /* ldw -18(r1),r1 */ 008: 0xe820c002 /* bv,n r0(r1) */ 00c: 0xe83f1fdf /* b,l,n .-c,r1 */ When a Code sequences that is to be patched spans a page break, we might have already cleared the part on the PAGE A. If an interrupt is coming in during the remap of the fixed mapping to PAGE B, it might execute the patched function with only parts of the FTRACE code cleared. To prevent this, clear the jump to our mini trampoline first, and clear the remaining parts after this. This might also happen when patch_text() patches a function that it calls during remap. Signed-off-by: Sven Schnelle Cc: # 5.2+ Signed-off-by: Helge Deller --- diff --git a/arch/parisc/kernel/ftrace.c b/arch/parisc/kernel/ftrace.c index d784ccdd8fef6..b6fb30f2e4bfd 100644 --- a/arch/parisc/kernel/ftrace.c +++ b/arch/parisc/kernel/ftrace.c @@ -181,8 +181,9 @@ int ftrace_make_nop(struct module *mod, struct dyn_ftrace *rec, for (i = 0; i < ARRAY_SIZE(insn); i++) insn[i] = INSN_NOP; + __patch_text((void *)rec->ip, INSN_NOP); __patch_text_multiple((void *)rec->ip + 4 - sizeof(insn), - insn, sizeof(insn)); + insn, sizeof(insn)-4); return 0; } #endif