NetBSD Problem Report #59955

From www@netbsd.org  Sun Feb  1 20:29:43 2026
Return-Path: <www@netbsd.org>
Received: from mail.netbsd.org (mail.netbsd.org [199.233.217.200])
	(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)
	 key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256
	 client-signature RSA-PSS (2048 bits) client-digest SHA256)
	(Client CN "mail.netbsd.org", Issuer "R13" (verified OK))
	by mollari.NetBSD.org (Postfix) with ESMTPS id 35C411A923D
	for <gnats-bugs@gnats.NetBSD.org>; Sun,  1 Feb 2026 20:29:43 +0000 (UTC)
Message-Id: <20260201202941.896A01A923E@mollari.NetBSD.org>
Date: Sun,  1 Feb 2026 20:29:41 +0000 (UTC)
From: campbell+netbsd@mumble.net
Reply-To: campbell+netbsd@mumble.net
To: gnats-bugs@NetBSD.org
Subject: kernel diagnostic assertion "rw_lock_held(&map->lock)" failed: file "/home/riastradh/netbsd/11/src/sys/uvm/uvm_map.c", line 1704
X-Send-Pr-Version: www-1.0
X-From4GNATS: "campbell+netbsd@mumble.net via gnats" <gnats-admin@NetBSD.org>

>Number:         59955
>Category:       kern
>Synopsis:       kernel diagnostic assertion "rw_lock_held(&map->lock)" failed: file "/home/riastradh/netbsd/11/src/sys/uvm/uvm_map.c", line 1704
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    kern-bug-people
>State:          needs-pullups
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Sun Feb 01 20:30:00 +0000 2026
>Closed-Date:    
>Last-Modified:  Fri May 22 14:35:13 +0000 2026
>Originator:     Taylor R Campbell
>Release:        11
>Organization:
The NetUVM Concrashulations, Inc.
>Environment:
>Description:
I started crash(8) and typed `ps', and the system panicked:

[ 598835.709592] panic: kernel diagnostic assertion "rw_lock_held(&map->lock)" failed: file "/home/riastradh/netbsd/11/src/sys/uvm/uvm_map.c", line 1704
[ 598835.709592] cpu1: Begin traceback...
[ 598835.710592] vpanic() at netbsd:vpanic+0x171
[ 598835.712592] kern_assert() at netbsd:kern_assert+0x4b
[ 598835.713592] uvm_map_lookup_entry() at netbsd:uvm_map_lookup_entry+0x99
[ 598835.715592] uvm_map_checkprot() at netbsd:uvm_map_checkprot+0x24
[ 598835.716591] mm_md_kernacc() at netbsd:mm_md_kernacc+0xc5
[ 598835.717591] mm_readwrite() at netbsd:mm_readwrite+0x295
[ 598835.719591] cdev_read() at netbsd:cdev_read+0x87
[ 598835.720592] spec_read() at netbsd:spec_read+0x328
[ 598835.722592] VOP_READ() at netbsd:VOP_READ+0x42
[ 598835.724592] vn_read() at netbsd:vn_read+0x98
[ 598835.726592] dofileread() at netbsd:dofileread+0x79
[ 598835.727592] sys_pread() at netbsd:sys_pread+0x95
[ 598835.729593] syscall() at netbsd:syscall+0x9d
[ 598835.729593] --- syscall (number 173) ---
[ 598835.730593] netbsd:syscall+0x9d:
[ 598835.730593] cpu1: End traceback...

[ 598835.733592] dumping to dev 168,12 (offset=527151, size=16710810):

>From the crash dump in gdb:

(gdb) bt
#0  0xffffffff80239b85 in cpu_reboot (howto=howto@entry=260,
    bootstr=bootstr@entry=0x0)
    at /home/riastradh/netbsd/11/src/sys/arch/amd64/amd64/machdep.c:709
#1  0xffffffff80ded195 in kern_reboot (howto=howto@entry=260,
    bootstr=bootstr@entry=0x0)
    at /home/riastradh/netbsd/11/src/sys/kern/kern_reboot.c:91
#2  0xffffffff80e32dc3 in vpanic (
    fmt=0xffffffff8162e748 "kernel %sassertion \"%s\" failed: file \"%s\", line %d ", ap=ap@entry=0xffffa41265273ba8)
    at /home/riastradh/netbsd/11/src/sys/kern/subr_prf.c:288
#3  0xffffffff81002c9e in kern_assert (
    fmt=fmt@entry=0xffffffff8162e748 "kernel %sassertion \"%s\" failed: file \"%s\", line %d ")
    at /home/riastradh/netbsd/11/src/sys/lib/libkern/kern_assert.c:51
#4  0xffffffff80d8c1e1 in uvm_map_lookup_entry (
    map=map@entry=0xffffffff81ac4800 <module_map_store>,
    address=address@entry=18446744071629767768,
    entry=entry@entry=0xffffa41265273c38)
    at /home/riastradh/netbsd/11/src/sys/uvm/uvm_map.c:1723
#5  0xffffffff80d901d7 in uvm_map_checkprot (
    map=0xffffffff81ac4800 <module_map_store>,
    start=start@entry=18446744071629767768,
    end=end@entry=18446744071629767769, protection=protection@entry=1)
    at /home/riastradh/netbsd/11/src/sys/uvm/uvm_map.c:4137
#6  0xffffffff8023a448 in mm_md_kernacc (ptr=ptr@entry=0xffffffff84090458,
    prot=prot@entry=1, handled=handled@entry=0xffffa41265273c97)
    at /home/riastradh/netbsd/11/src/sys/arch/amd64/amd64/machdep.c:2278
#7  0xffffffff80ed7a7d in dev_kmem_readwrite (iov=<optimized out>,
    uio=0xffffa41265273ee0) at /home/riastradh/netbsd/11/src/sys/dev/mm.c:274
#8  mm_readwrite (dev=<optimized out>, uio=0xffffa41265273ee0,
    flags=<optimized out>) at /home/riastradh/netbsd/11/src/sys/dev/mm.c:349
#9  0xffffffff80e1d2bc in cdev_read (dev=513,
    uio=uio@entry=0xffffa41265273ee0, flag=0)
    at /home/riastradh/netbsd/11/src/sys/kern/subr_devsw.c:1499
#10 0xffffffff80ec5132 in spec_read (v=0xffffa41265273e38)
    at /home/riastradh/netbsd/11/src/sys/miscfs/specfs/spec_vnops.c:1127
#11 0xffffffff80eb6582 in VOP_READ (vp=vp@entry=0xffff9f662269e080,
    uio=uio@entry=0xffffa41265273ee0, ioflag=ioflag@entry=0,
    cred=cred@entry=0xffff9f6aee98bc40)
    at /home/riastradh/netbsd/11/src/sys/kern/vnode_if.c:785
#12 0xffffffff80ead067 in vn_read (fp=<optimized out>,
    offset=0xffffa41265273f68, uio=0xffffa41265273ee0,
    cred=0xffff9f6aee98bc40, flags=<optimized out>)
    at /home/riastradh/netbsd/11/src/sys/kern/vfs_vnops.c:675
#13 0xffffffff80e46f7d in dofileread (fd=fd@entry=5,
    fp=fp@entry=0xffff9f61121327c0, buf=0x7f7fff4c1cf0, nbyte=1,
    offset=offset@entry=0xffffa41265273f68, flags=flags@entry=0,
    retval=retval@entry=0xffffa41265273fb0)
    at /home/riastradh/netbsd/11/src/sys/kern/sys_generic.c:156
#14 0xffffffff80ea1879 in sys_pread (l=<optimized out>,
    uap=0xffffa41265274000, retval=0xffffa41265273fb0)
    at /home/riastradh/netbsd/11/src/sys/kern/vfs_syscalls.c:3056
#15 0xffffffff805c0ca1 in sy_call (rval=0xffffa41265273fb0,
    uap=0xffffa41265274000, l=0xffff9f634ed85400,
    sy=0xffffffff81a88af8 <sysent+4152>)
    at /home/riastradh/netbsd/11/src/sys/sys/syscallvar.h:65
#16 sy_invoke (code=173, rval=0xffffa41265273fb0, uap=0xffffa41265274000,
    l=0xffff9f634ed85400, sy=0xffffffff81a88af8 <sysent+4152>)
    at /home/riastradh/netbsd/11/src/sys/sys/syscallvar.h:94
#17 syscall (frame=0xffffa41265274000)
    at /home/riastradh/netbsd/11/src/sys/arch/x86/x86/syscall.c:137
#18 0xffffffff8021025d in handle_syscall ()

Relevant excerpt of code:

1679 /*
1680  * uvm_map_lookup_entry: find map entry at or before an address
1681  *
1682  * => map must at least be read-locked by caller.
1683  *
1684  * => If address lies in an entry, set *entry to it and return true;
1685  *    then (*entry)->start <= address < (*entry)->end.
1686 
1687  * => If address is below all entries in map, return false and set
1688  *    *entry to &map->header.
1689  *
1690  * => Otherwise, return false and set *entry to the highest entry below
1691  *    address, so (*entry)->end <= address, and if (*entry)->next is
1692  *    not &map->header, address < (*entry)->next->start.
1693  */
1694 
1695 bool
1696 uvm_map_lookup_entry(struct vm_map *map, vaddr_t address,
1697     struct vm_map_entry **entry	/* OUT */)
1698 {
1699 	struct vm_map_entry *cur;
1700 	UVMHIST_FUNC(__func__);
1701 	UVMHIST_CALLARGS(maphist,"(map=%#jx,addr=%#jx,ent=%#jx)",
1702 	    (uintptr_t)map, address, (uintptr_t)entry, 0);
1703 
1704 	KASSERT(rw_lock_held(&map->lock));

https://nxr.netbsd.org/xref/src/sys/uvm/uvm_map.c?r=1.427#1704

This is called from:

2240 int
2241 mm_md_kernacc(void *ptr, vm_prot_t prot, bool *handled)
...
2276 	if (v >= bootspace.smodule && v < bootspace.emodule) {
2277 		*handled = true;
2278 		if (!uvm_map_checkprot(module_map, v, v + 1, prot)) {
2279 			return EFAULT;
2280 		}
2281 	} else {
2282 		*handled = false;
2283 	}

https://nxr.netbsd.org/xref/src/sys/arch/amd64/amd64/machdep.c?r=1.376#2278

But module_map is not locked at this point.

Apparently I added this assertion relatively recently, for:

PR kern/51254: uvm assertion "!topdown || hint <= orig_hint" failed

https://mail-index.netbsd.org/source-changes/2024/08/13/msg152763.html

It's probably not safe to do this without the map lock.
>How-To-Repeat:
Make sure modules are loaded and (insert additional criteria here) and:

# crash
crash> ps
>Fix:
1. Verify this path isn't used by ddb, or allow unlocked access by ddb in the assertion.
2. Take the map lock in mm_md_kernacc.
3. Audit other callers of uvm_map_checkprot.

>Release-Note:

>Audit-Trail:
From: Taylor R Campbell <riastradh@NetBSD.org>
To: gnats-bugs@NetBSD.org, netbsd-bugs@NetBSD.org
Cc: chs@NetBSD.org
Subject: Re: kern/59955: kernel diagnostic assertion "rw_lock_held(&map->lock)" failed: file "/home/riastradh/netbsd/11/src/sys/uvm/uvm_map.c", line 1704
Date: Sun, 1 Feb 2026 20:37:45 +0000

 Actually, just taking the read lock in mm_md_kernacc probably isn't
 enough, because we really need the access to _remain_ allowed while we
 do the uiomove in dev/mm.c.  Can we hold the map lock across uiomove?
 Sounds unlikely.  Can we wire the pages with uvm_vslock or something
 across the uvm_map_checkprot and uiomove?

From: Chuck Silvers <chuq@chuq.com>
To: Taylor R Campbell <riastradh@NetBSD.org>
Cc: gnats-bugs@NetBSD.org, netbsd-bugs@NetBSD.org
Subject: Re: kern/59955: kernel diagnostic assertion
 "rw_lock_held(&map->lock)" failed: file
 "/home/riastradh/netbsd/11/src/sys/uvm/uvm_map.c", line 1704
Date: Sun, 1 Feb 2026 17:55:43 -0800

 On Sun, Feb 01, 2026 at 08:37:45PM +0000, Taylor R Campbell wrote:
 > Actually, just taking the read lock in mm_md_kernacc probably isn't
 > enough, because we really need the access to _remain_ allowed while we
 > do the uiomove in dev/mm.c.  Can we hold the map lock across uiomove?
 > Sounds unlikely.  Can we wire the pages with uvm_vslock or something
 > across the uvm_map_checkprot and uiomove?

 there is no need to call uvm_map_checkprot() here.  if uiomove() faults
 while trying to access an unmapped address within module_map, it will just
 fail with an error, which is what you'd want anyway.

 -Chuck

From: "Taylor R Campbell" <riastradh@netbsd.org>
To: gnats-bugs@gnats.NetBSD.org
Cc: 
Subject: PR/59955 CVS commit: src/sys/arch/amd64/amd64
Date: Sun, 22 Feb 2026 12:14:56 +0000

 Module Name:	src
 Committed By:	riastradh
 Date:		Sun Feb 22 12:14:56 UTC 2026

 Modified Files:
 	src/sys/arch/amd64/amd64: machdep.c

 Log Message:
 amd64: Fix locking around uvm_map_checkprot in mm_md_kernacc.

 This call was originally introduced in sys/arch/amd64/amd64/mem.c
 rev. 1.11 back in 2003 by fvdl@ with the commit message:

 > Proper checks for kmem reads beyond _end

 https://mail-index.netbsd.org/source-changes/2003/10/14/msg135803.html

 At some point, SOMEBODY added an assertion in uvm that made it stop
 working:

 > uvm_map(9): Sprinkle assertions and interface contract comments.
 >
 > No functional change intended.

 https://mail-index.netbsd.org/source-changes/2024/08/13/msg152763.html

 (Really, this assertion revealed that this path was broken all along.)

 This patch makes the amd64 mm_md_kernacc match the corresponding logic
 in uvm_kernacc around uvm_map_checkprot:

     104 	vm_map_lock_read(kernel_map);
     105 	rv = uvm_map_checkprot(kernel_map, saddr, eaddr, prot);
     106 	vm_map_unlock_read(kernel_map);

 https://nxr.netbsd.org/xref/src/sys/uvm/uvm_glue.c#92

 Now, all of these checks in /dev/mem and company look like TOCTOU
 bogosity, because the answers are stale by the time we reach uiomove,
 which has to re-check any access anyway:

     269 	if (!md_kva) {
     270 		bool checked = false;
     271
     272 #ifdef __HAVE_MM_MD_KERNACC
     273 		/* MD check for the address. */
     274 		error = mm_md_kernacc(addr, prot, &checked);
     275 		if (error) {
     276 			return error;
     277 		}
     278 #endif
     279 		/* UVM check for the address (unless MD indicated to not). */
     280 		if (!checked && !uvm_kernacc(addr, len, prot)) {
     281 			return EFAULT;
     282 		}
     283 	}
     284 	error = uiomove(addr, len, uio);

 https://nxr.netbsd.org/xref/src/sys/dev/mm.c?r=1.25#269

 But we can address that in a separate change.

 PR kern/59955: kernel diagnostic assertion "rw_lock_held(&map->lock)"
 failed: file "/home/riastradh/netbsd/11/src/sys/uvm/uvm_map.c", line
 1704


 To generate a diff of this commit:
 cvs rdiff -u -r1.378 -r1.379 src/sys/arch/amd64/amd64/machdep.c

 Please note that diffs are not public domain; they are subject to the
 copyright notices on the relevant files.

From: "Martin Husemann" <martin@netbsd.org>
To: gnats-bugs@gnats.NetBSD.org
Cc: 
Subject: PR/59955 CVS commit: [netbsd-11] src/sys/arch/amd64/amd64
Date: Wed, 4 Mar 2026 20:05:59 +0000

 Module Name:	src
 Committed By:	martin
 Date:		Wed Mar  4 20:05:58 UTC 2026

 Modified Files:
 	src/sys/arch/amd64/amd64 [netbsd-11]: machdep.c

 Log Message:
 Pull up following revision(s) (requested by riastradh in ticket #199):

 	sys/arch/amd64/amd64/machdep.c: revision 1.379

 amd64: Fix locking around uvm_map_checkprot in mm_md_kernacc.

 This call was originally introduced in sys/arch/amd64/amd64/mem.c
 rev. 1.11 back in 2003 by fvdl@ with the commit message:

 Proper checks for kmem reads beyond _end
 https://mail-index.netbsd.org/source-changes/2003/10/14/msg135803.html

 At some point, SOMEBODY added an assertion in uvm that made it stop
 working:
 uvm_map(9): Sprinkle assertions and interface contract comments.
 No functional change intended.

 https://mail-index.netbsd.org/source-changes/2024/08/13/msg152763.html
 (Really, this assertion revealed that this path was broken all along.)

 This patch makes the amd64 mm_md_kernacc match the corresponding logic
 in uvm_kernacc around uvm_map_checkprot:
     104         vm_map_lock_read(kernel_map);
     105         rv = uvm_map_checkprot(kernel_map, saddr, eaddr, prot);
     106         vm_map_unlock_read(kernel_map);
 https://nxr.netbsd.org/xref/src/sys/uvm/uvm_glue.c#92

 Now, all of these checks in /dev/mem and company look like TOCTOU
 bogosity, because the answers are stale by the time we reach uiomove,
 which has to re-check any access anyway:
     269         if (!md_kva) {
     270                 bool checked = false;
     271
     272 #ifdef __HAVE_MM_MD_KERNACC
     273                 /* MD check for the address. */
     274                 error = mm_md_kernacc(addr, prot, &checked);
     275                 if (error) {
     276                         return error;
     277                 }
     278 #endif
     279                 /* UVM check for the address (unless MD indicated to not). */
     280                 if (!checked && !uvm_kernacc(addr, len, prot)) {
     281                         return EFAULT;
     282                 }
     283         }
     284         error = uiomove(addr, len, uio);
 https://nxr.netbsd.org/xref/src/sys/dev/mm.c?r=1.25#269
 But we can address that in a separate change.

 PR kern/59955: kernel diagnostic assertion "rw_lock_held(&map->lock)"
 failed: file "/home/riastradh/netbsd/11/src/sys/uvm/uvm_map.c", line
 1704


 To generate a diff of this commit:
 cvs rdiff -u -r1.376 -r1.376.2.1 src/sys/arch/amd64/amd64/machdep.c

 Please note that diffs are not public domain; they are subject to the
 copyright notices on the relevant files.

State-Changed-From-To: open->needs-pullups
State-Changed-By: riastradh@NetBSD.org
State-Changed-When: Fri, 22 May 2026 14:35:13 +0000
State-Changed-Why:
fixed in HEAD, needs pullup-11, pullup-10, pullup-9


>Unformatted:

NetBSD Home
NetBSD PR Database Search

(Contact us) $NetBSD: query-full-pr,v 1.51 2026/08/10 02:28:17 riastradh Exp $
$NetBSD: gnats_config.sh,v 1.10 2026/05/13 22:00:09 riastradh Exp $
Copyright © 1994-2026 The NetBSD Foundation, Inc. ALL RIGHTS RESERVED.