All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] sh: mm: fix double mmap_lock release on SIGBUS and SIGSEGV faults
@ 2026-09-28  0:19 Karl Mehltretter
  2026-10-16  9:46 ` Karl Mehltretter
  0 siblings, 1 reply; 3+ messages in thread
From: Karl Mehltretter @ 2026-09-28  0:19 UTC (permalink / raw)
  To: Yoshinori Sato, Rich Felker, John Paul Adrian Glaubitz
  Cc: Karl Mehltretter, Peter Xu, Andrew Morton, linux-sh, linux-kernel

Since commit fb027ada051a ("sh/mm: use helper fault_signal_pending()"),
mm_fault_error() releases mmap_lock itself for every fault result
without VM_FAULT_RETRY. Before that, the VM_FAULT_SIGBUS and
VM_FAULT_SIGSEGV branches relied on do_sigbus() and bad_area() to
release it, and both still do. So a fault that ends in SIGBUS or
SIGSEGV releases mmap_lock twice.

A process that survives the signal keeps an mm with a corrupted
mmap_lock. With CONFIG_DEBUG_RWSEMS and lockdep, stress-ng --msync
(which catches SIGBUS) reports within a minute:

  WARNING: bad unlock balance detected!
  stress-ng-msync/54 is trying to release lock (&mm->mmap_lock) at:
  mm_fault_error+0xd0/0x16c
  ...
  DEBUG_RWSEMS_WARN_ON(tmp < 0): count = 0xffffff00, ...

and without them, find_vma() warns that mmap_lock is not held right
after it was taken. Seen on a custom QEMU model of the SH7785LCR, in
both 29-bit and 32-bit mode.

Drop the release from do_sigbus(), whose only caller is
mm_fault_error(), and use bad_area_nosemaphore() for VM_FAULT_SIGSEGV.
bad_area() has no users left and goes away.

Fixes: fb027ada051a ("sh/mm: use helper fault_signal_pending()")
Cc: stable@vger.kernel.org
Assisted-by: LLM
Signed-off-by: Karl Mehltretter <kmehltretter@gmail.com>
---

Notes:
    Tested in QEMU on a custom SH7785LCR model, not on hardware.
    Reproducer: Debian sh4 stress-ng 0.22.01 --msync

    Unpatched:
    - debug kernel: lockdep "bad unlock balance", DEBUG_RWSEMS count
      0xffffff00
    - 29-bit and 32-bit non-debug kernels: find_vma() mmap_lock warnings

    Patched (debug kernel):
    - stress-ng --msync passes, no lock reports
    - stress-ng run with 48 stressors: no kernel reports

    Testing on real hardware is welcome.

 arch/sh/mm/fault.c | 13 +------------
 1 file changed, 1 insertion(+), 12 deletions(-)

diff --git a/arch/sh/mm/fault.c b/arch/sh/mm/fault.c
index 06e6b49529245..138fc577a4c13 100644
--- a/arch/sh/mm/fault.c
+++ b/arch/sh/mm/fault.c
@@ -281,12 +281,6 @@ __bad_area(struct pt_regs *regs, unsigned long error_code,
 	__bad_area_nosemaphore(regs, error_code, address, si_code);
 }
 
-static noinline void
-bad_area(struct pt_regs *regs, unsigned long error_code, unsigned long address)
-{
-	__bad_area(regs, error_code, address, SEGV_MAPERR);
-}
-
 static noinline void
 bad_area_access_error(struct pt_regs *regs, unsigned long error_code,
 		      unsigned long address)
@@ -297,11 +291,6 @@ bad_area_access_error(struct pt_regs *regs, unsigned long error_code,
 static void
 do_sigbus(struct pt_regs *regs, unsigned long error_code, unsigned long address)
 {
-	struct task_struct *tsk = current;
-	struct mm_struct *mm = tsk->mm;
-
-	mmap_read_unlock(mm);
-
 	/* Kernel mode? Handle exceptions or die: */
 	if (!user_mode(regs))
 		no_context(regs, error_code, address);
@@ -347,7 +336,7 @@ mm_fault_error(struct pt_regs *regs, unsigned long error_code,
 		if (fault & VM_FAULT_SIGBUS)
 			do_sigbus(regs, error_code, address);
 		else if (fault & VM_FAULT_SIGSEGV)
-			bad_area(regs, error_code, address);
+			bad_area_nosemaphore(regs, error_code, address);
 		else
 			BUG();
 	}
-- 
2.53.0


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

end of thread, other threads:[~2026-10-16 13:50 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-28  0:19 [PATCH] sh: mm: fix double mmap_lock release on SIGBUS and SIGSEGV faults Karl Mehltretter
2026-10-16  9:46 ` Karl Mehltretter
2026-10-16 13:50   ` John Paul Adrian Glaubitz

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.