[<prev] [next>] [day] [month] [year] [list]
Message-Id: <20251128-fix_mips_ftrace-v1-1-e6169f8777f2@bootlin.com>
Date: Fri, 28 Nov 2025 09:30:06 +0100
From: Gregory CLEMENT <gregory.clement@...tlin.com>
To: Steven Rostedt <rostedt@...dmis.org>,
Masami Hiramatsu <mhiramat@...nel.org>, Mark Rutland <mark.rutland@....com>,
Thomas Bogendoerfer <tsbogend@...ha.franken.de>
Cc: Vladimir Kondratiev <vladimir.kondratiev@...ileye.com>,
Théo Lebrun <theo.lebrun@...tlin.com>,
Benoît Monin <benoit.monin@...tlin.com>,
Thomas Petazzoni <thomas.petazzoni@...tlin.com>,
linux-kernel@...r.kernel.org, linux-trace-kernel@...r.kernel.org,
linux-mips@...r.kernel.org, Gregory CLEMENT <gregory.clement@...tlin.com>
Subject: [PATCH] MIPS: ftrace: Fix memory corruption when kernel is located
beyond 32 bits
Since commit e424054000878 ("MIPS: Tracing: Reduce the overhead of
dynamic Function Tracer"), the macro UASM_i_LA_mostly has been used,
and this macro can generate more than 2 instructions. At the same
time, the code in ftrace assumes that no more than 2 instructions can
be generated, which is why it stores them in an int[2] array. However,
as previously noted, the macro UASM_i_LA_mostly (and now UASM_i_LA)
causes a buffer overflow when _mcount is beyond 32 bits. This leads to
corruption of the variables located in the __read_mostly section.
This corruption was observed because the variable
__cpu_primary_thread_mask was corrupted, causing a hang very early
during boot.
This fix prevents the corruption by avoiding the generation of
instructions if they could exceed 2 instructions in
length. Fortunately, insn_la_mcount is only used if the instrumented
code is located outside the kernel code section, so dynamic ftrace can
still be used, albeit in a more limited scope. This is still
preferable to corrupting memory and/or crashing the kernel.
Signed-off-by: Gregory CLEMENT <gregory.clement@...tlin.com>
---
To go further and remove the limitations of dynamic trace support, the
ftrace implementation for MIPS should be completely rewritten and
inspired by what was done for arm64. This approach was chosen by
Loongson: instead of trying to manage multiple instructions added on
the fly, the support relies on a breakpoint, which is more robust.
However, this effort is significant, so I’ll leave it to those who are
motivated to work on it. If needed, I can provide some guidance on the
topic.
---
arch/mips/kernel/ftrace.c | 25 +++++++++++++++++++++----
1 file changed, 21 insertions(+), 4 deletions(-)
diff --git a/arch/mips/kernel/ftrace.c b/arch/mips/kernel/ftrace.c
index f39e85fd58fa9..b15615b285690 100644
--- a/arch/mips/kernel/ftrace.c
+++ b/arch/mips/kernel/ftrace.c
@@ -54,10 +54,20 @@ static inline void ftrace_dyn_arch_init_insns(void)
u32 *buf;
unsigned int v1;
- /* la v1, _mcount */
- v1 = 3;
- buf = (u32 *)&insn_la_mcount[0];
- UASM_i_LA(&buf, v1, MCOUNT_ADDR);
+ /* If we are not in compat space, the number of generated
+ * instructions will exceed the maximum expected limit of 2.
+ * To prevent buffer overflow, we avoid generating them.
+ * insn_la_mcount will not be used later in ftrace_make_call.
+ */
+ if (uasm_in_compat_space_p(MCOUNT_ADDR)) {
+ /* la v1, _mcount */
+ v1 = 3;
+ buf = (u32 *)&insn_la_mcount[0];
+ UASM_i_LA(&buf, v1, MCOUNT_ADDR);
+ } else {
+ pr_warn("ftrace: mcount address beyond 32 bits is not supported (%lX)\n",
+ MCOUNT_ADDR);
+ }
/* jal (ftrace_caller + 8), jump over the first two instruction */
buf = (u32 *)&insn_jal_ftrace_caller;
@@ -189,6 +199,13 @@ int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
unsigned int new;
unsigned long ip = rec->ip;
+ /* When the code to patch does not belong to the kernel code
+ * space, we must use insn_la_mcount. However, if MCOUNT_ADDR
+ * is not in compat space, insn_la_mcount is not usable.
+ */
+ if (!core_kernel_text(ip) && !uasm_in_compat_space_p(MCOUNT_ADDR))
+ return -EFAULT;
+
new = core_kernel_text(ip) ? insn_jal_ftrace_caller : insn_la_mcount[0];
#ifdef CONFIG_64BIT
---
base-commit: 3a8660878839faadb4f1a6dd72c3179c1df56787
change-id: 20251104-fix_mips_ftrace-7aaab89e3f77
Best regards,
--
Grégory CLEMENT, Bootlin
Embedded Linux and Kernel engineering
https://bootlin.com
Powered by blists - more mailing lists