* [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* Re: [PATCH] sh: mm: fix double mmap_lock release on SIGBUS and SIGSEGV faults
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
0 siblings, 1 reply; 3+ messages in thread
From: Karl Mehltretter @ 2026-10-16 9:46 UTC (permalink / raw)
To: Yoshinori Sato, Rich Felker, John Paul Adrian Glaubitz
Cc: Peter Xu, Andrew Morton, linux-sh, linux-kernel
On Mon, Sep 28, 2026 at 02:19:37AM +0100, Karl Mehltretter wrote:
> 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
>
A friendly ping on this fix.
I have now also reproduced it with stock QEMU 11.0.2 on the upstream
r2d machine (SH7751R): the unpatched kernel warns after a caught SIGBUS,
while the patched kernel does not.
Also, the stress-ng command in the review notes is incorrect. Use:
stress-ng --msync 1 --timeout 60s
Thanks,
Karl
^ permalink raw reply [flat|nested] 3+ messages in thread* Re: [PATCH] sh: mm: fix double mmap_lock release on SIGBUS and SIGSEGV faults
2026-10-16 9:46 ` Karl Mehltretter
@ 2026-10-16 13:50 ` John Paul Adrian Glaubitz
0 siblings, 0 replies; 3+ messages in thread
From: John Paul Adrian Glaubitz @ 2026-10-16 13:50 UTC (permalink / raw)
To: Karl Mehltretter, Yoshinori Sato, Rich Felker
Cc: Peter Xu, Andrew Morton, linux-sh, linux-kernel
Hi Karl,
On Fri, 2026-10-16 at 11:46 +0200, Karl Mehltretter wrote:
> On Mon, Sep 28, 2026 at 02:19:37AM +0100, Karl Mehltretter wrote:
> > 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
> >
>
> A friendly ping on this fix.
>
> I have now also reproduced it with stock QEMU 11.0.2 on the upstream
> r2d machine (SH7751R): the unpatched kernel warns after a caught SIGBUS,
> while the patched kernel does not.
>
> Also, the stress-ng command in the review notes is incorrect. Use:
>
> stress-ng --msync 1 --timeout 60s
I'm trying to get this reviewed in the weekend. I'm not forgetting about
patches as I'll always check what's on patchwork and pick everything up
that I haven't taken yet [1].
Adrian
> [1] https://patchwork.kernel.org/project/linux-sh/list/
--
.''`. John Paul Adrian Glaubitz
: :' : Debian Developer
`. `' Physicist
`- GPG: 62FF 8A75 84E0 2956 9546 0006 7426 3B37 F5B5 F913
^ permalink raw reply [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.