linux-trace-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] MIPS: ftrace: Fix memory corruption when kernel is located beyond 32 bits
@ 2025-11-28  8:30 Gregory CLEMENT
  2025-12-02  8:37 ` Thomas Bogendoerfer
  0 siblings, 1 reply; 2+ messages in thread
From: Gregory CLEMENT @ 2025-11-28  8:30 UTC (permalink / raw)
  To: Steven Rostedt, Masami Hiramatsu, Mark Rutland,
	Thomas Bogendoerfer
  Cc: Vladimir Kondratiev, Théo Lebrun, Benoît Monin,
	Thomas Petazzoni, linux-kernel, linux-trace-kernel, linux-mips,
	Gregory CLEMENT

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@bootlin.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


^ permalink raw reply related	[flat|nested] 2+ messages in thread

* Re: [PATCH] MIPS: ftrace: Fix memory corruption when kernel is located beyond 32 bits
  2025-11-28  8:30 [PATCH] MIPS: ftrace: Fix memory corruption when kernel is located beyond 32 bits Gregory CLEMENT
@ 2025-12-02  8:37 ` Thomas Bogendoerfer
  0 siblings, 0 replies; 2+ messages in thread
From: Thomas Bogendoerfer @ 2025-12-02  8:37 UTC (permalink / raw)
  To: Gregory CLEMENT
  Cc: Steven Rostedt, Masami Hiramatsu, Mark Rutland,
	Vladimir Kondratiev, Théo Lebrun, Benoît Monin,
	Thomas Petazzoni, linux-kernel, linux-trace-kernel, linux-mips

On Fri, Nov 28, 2025 at 09:30:06AM +0100, Gregory CLEMENT wrote:
> 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@bootlin.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(-)

applied to mips-next.

Thomas.

-- 
Crap can work. Given enough thrust pigs will fly, but it's not necessarily a
good idea.                                                [ RFC1925, 2.3 ]

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2025-12-02  8:45 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-11-28  8:30 [PATCH] MIPS: ftrace: Fix memory corruption when kernel is located beyond 32 bits Gregory CLEMENT
2025-12-02  8:37 ` Thomas Bogendoerfer

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).