Hi Sergei,

On Thu, Feb 13, 2025 at 01:35:13PM +0300, Sergei Golovan wrote:
> tag 1086028 + patch
> tag 1087809 + patch
> tag 1093200 + patch
> thanks
> 
> Hi!
> 
> I've finally managed to reproduce this EFAULT in QEMU (using an
> Erlang-based script which is shipped in the wings3d source package):
> 
> 1) I've installed Debian bookworm for mips64el in qemu-system-mips64el
> virtual machine (version from unstable), and upgraded it to the
> current unstable (machine is loongson3-virt, cpu is Loongson-3A4000).
> 2) I have to enable SMP in qemu and use -rtc clock=rt (otherwise the
> virtual machine won't boot, with clock=rt sometimes it boots,
> sometimes it hangs). The full QEMU command line is:
> 
> qemu-system-mips64el -machine loongson3-virt -m 4g -cpu Loongson-3A4000 \
>             -smp 2,sockets=2,cores=1,threads=1,maxcpus=2 \
>             -kernel vmlinuz-loongson-3  \
>             -rtc clock=rt \
>             -initrd initrd.img-loongson-3 -drive
> if=none,file=hda1.bin,id=hd,format=raw  \
>             -net nic -net tap,ifname=tap0,script=/bin/true \
>             -device virtio-blk-pci,drive=hd -append "root=/dev/vda1
> console=ttyS0" \
>             -nographic
> 
> Here kernel and initrd can be either stock 6.1.123-1 version or
> 6.1.123-1 with the attached patch. Unfortunately, QEMU can't boot for
> me using the newest 6.12.12-1 kernel (it complains that it can't
> uncompress initrd, I don't know why).
> 
> 4) I've install the build dependencies of wings3d (basically, only
> erlang-base is necessary)
> 5) I've extracted the wings3d source package (from stable:
> https://packages.debian.org/source/stable/wings3d)
> 6) I've added the following line as the second line to
> wings3d-2.2.9/intl_tools/gen_char_hrl
> 
> %%! +S 4:4 +SDcpu 4:4 +c false
> 
> (The first two options enable multiple threads, the last one allows
> some workaround for the case when monotonic clock jumps backwards,
> which appears to be the case for QEMU with SMP enabled).
> 7) I've run this gen_char_hrl in a loop until it fails.
> 
> The result is that with the stock 6.1.123-1 kernel approximately in 1%
> cases the script aborts with message:
> 
> signal-dispatcher thread got unexpected error: efault (14)
> 
> which is exactly the error that prevents Erlang (and many Erlang-based
> packages) from building on mips64el.
> 
> On the other hand, with the patched kernel the script loop is still
> running for more than 24 hours (a few thousands runs) without
> aborting. So I'm now fairly confident that the patch fixes the bug.
> 
> I'm not sure if there's no adverse effects caused by the patch, so
> it'd be better to try it on real hardware as well.
> 
> The patch is derived from the thread [1]. It reverses commit [2] with
> an additional change, which is necessary because of changes in
> expand_stack() introduced in commit [3].
> 
> [1] https://lore.kernel.org/all/mvmplxraqmd....@suse.de/T/
> [2] 
> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=4bce37a68ff884e821a02a731897a8119e0c37b7
> [3] 
> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=8d7071af890768438c14db6172cc8f9f4d04e184

Can you test the two patched attached instead please?

Regards,
Salvatore
>From ea929a7413f6e7847cf2b7f75acfe750bc0d07e6 Mon Sep 17 00:00:00 2001
From: Jiaxun Yang <jiaxun.y...@flygoat.com>
Date: Fri, 2 Feb 2024 12:30:26 +0000
Subject: [PATCH 1/2] ptrace: Introduce exception_ip arch hook

commit 11ba1728be3edb6928791f4c622f154ebe228ae6 upstream.

On architectures with delay slot, architecture level instruction
pointer (or program counter) in pt_regs may differ from where
exception was triggered.

Introduce exception_ip hook to invoke architecture code and determine
actual instruction pointer to the exception.

Link: https://lore.kernel.org/lkml/00d1b813-c55f-4365-8d81-d70258e10...@app.fastmail.com/
Signed-off-by: Jiaxun Yang <jiaxun.y...@flygoat.com>
Signed-off-by: Thomas Bogendoerfer <tsbog...@alpha.franken.de>
Signed-off-by: Salvatore Bonaccorso <car...@debian.org>
---
 arch/mips/include/asm/ptrace.h | 2 ++
 arch/mips/kernel/ptrace.c      | 7 +++++++
 include/linux/ptrace.h         | 4 ++++
 3 files changed, 13 insertions(+)

diff --git a/arch/mips/include/asm/ptrace.h b/arch/mips/include/asm/ptrace.h
index 428b9f1cf1de..4a2b40ce39e0 100644
--- a/arch/mips/include/asm/ptrace.h
+++ b/arch/mips/include/asm/ptrace.h
@@ -155,6 +155,8 @@ static inline long regs_return_value(struct pt_regs *regs)
 }
 
 #define instruction_pointer(regs) ((regs)->cp0_epc)
+extern unsigned long exception_ip(struct pt_regs *regs);
+#define exception_ip(regs) exception_ip(regs)
 #define profile_pc(regs) instruction_pointer(regs)
 
 extern asmlinkage long syscall_trace_enter(struct pt_regs *regs);
diff --git a/arch/mips/kernel/ptrace.c b/arch/mips/kernel/ptrace.c
index a8e569830ec8..fdcaad9fba1d 100644
--- a/arch/mips/kernel/ptrace.c
+++ b/arch/mips/kernel/ptrace.c
@@ -31,6 +31,7 @@
 #include <linux/seccomp.h>
 #include <linux/ftrace.h>
 
+#include <asm/branch.h>
 #include <asm/byteorder.h>
 #include <asm/cpu.h>
 #include <asm/cpu-info.h>
@@ -48,6 +49,12 @@
 #define CREATE_TRACE_POINTS
 #include <trace/events/syscalls.h>
 
+unsigned long exception_ip(struct pt_regs *regs)
+{
+	return exception_epc(regs);
+}
+EXPORT_SYMBOL(exception_ip);
+
 /*
  * Called by kernel/ptrace.c when detaching..
  *
diff --git a/include/linux/ptrace.h b/include/linux/ptrace.h
index c952c5ba8fab..135a3d9140a0 100644
--- a/include/linux/ptrace.h
+++ b/include/linux/ptrace.h
@@ -402,6 +402,10 @@ static inline void user_single_step_report(struct pt_regs *regs)
 #define current_user_stack_pointer() user_stack_pointer(current_pt_regs())
 #endif
 
+#ifndef exception_ip
+#define exception_ip(x) instruction_pointer(x)
+#endif
+
 extern int task_current_syscall(struct task_struct *target, struct syscall_info *info);
 
 extern void sigaction_compat_abi(struct k_sigaction *act, struct k_sigaction *oact);
-- 
2.47.2

>From 35fbf9250388bca02a62609ef27532ab7c9654ca Mon Sep 17 00:00:00 2001
From: Jiaxun Yang <jiaxun.y...@flygoat.com>
Date: Fri, 2 Feb 2024 12:30:28 +0000
Subject: [PATCH 2/2] mm/memory: Use exception ip to search exception tables

commit 8fa5070833886268e4fb646daaca99f725b378e9 upstream.

On architectures with delay slot, instruction_pointer() may differ
from where exception was triggered.

Use exception_ip we just introduced to search exception tables to
get rid of the problem.

Fixes: 4bce37a68ff8 ("mips/mm: Convert to using lock_mm_and_find_vma()")
Reported-by: Xi Ruoyao <xry...@xry111.site>
Link: https://lore.kernel.org/r/75e9fd7b08562ad9b456a5bdaacb7cc220311cc9.ca...@xry111.site/
Suggested-by: Linus Torvalds <torva...@linux-foundation.org>
Signed-off-by: Jiaxun Yang <jiaxun.y...@flygoat.com>
Signed-off-by: Thomas Bogendoerfer <tsbog...@alpha.franken.de>
Signed-off-by: Salvatore Bonaccorso <car...@debian.org>
---
 mm/memory.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/mm/memory.c b/mm/memory.c
index da9fed5e6025..680d864d52eb 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -5323,7 +5323,7 @@ static inline bool get_mmap_lock_carefully(struct mm_struct *mm, struct pt_regs
 	}
 
 	if (regs && !user_mode(regs)) {
-		unsigned long ip = instruction_pointer(regs);
+		unsigned long ip = exception_ip(regs);
 		if (!search_exception_tables(ip))
 			return false;
 	}
@@ -5348,7 +5348,7 @@ static inline bool upgrade_mmap_lock_carefully(struct mm_struct *mm, struct pt_r
 {
 	mmap_read_unlock(mm);
 	if (regs && !user_mode(regs)) {
-		unsigned long ip = instruction_pointer(regs);
+		unsigned long ip = exception_ip(regs);
 		if (!search_exception_tables(ip))
 			return false;
 	}
-- 
2.47.2

Reply via email to