summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorMartin Pieuchot <mpi@cvs.openbsd.org>2020-10-07 12:26:21 +0000
committerMartin Pieuchot <mpi@cvs.openbsd.org>2020-10-07 12:26:21 +0000
commit0afe36204da3fa27fa61053c0f447b62e39fc14c (patch)
tree107ea21c11444b7567d1b49e194ad2487aaebfad /sys
parentdcb3de7f094fdccd130e961a883263400c9108e5 (diff)
Do not release the KERNEL_LOCK() when mmap(2)ing files.
Previous attempt to unlock amap & anon exposed a race in vnode reference counting. So be conservative with the code paths that we're not fully moving out of the KERNEL_LOCK() to allow us to concentrate on one area at a time. The panic reported was: ....panic: vref used where vget required ....db_enter() at db_enter+0x5 ....panic() at panic+0x129 ....vref(ffffff03b20d29e8) at vref+0x5d ....uvn_attach(1010000,ffffff03a5879dc0) at uvn_attach+0x11d ....uvm_mmapfile(7,ffffff03a5879dc0,2,1,13,100000012) at uvm_mmapfile+0x12c ....sys_mmap(c50,ffff8000225f82a0,1) at sys_mmap+0x604 ....syscall() at syscall+0x279 Note that this change has no effect as long as mmap(2) is still executed with ze big lock. ok kettenis@
Diffstat (limited to 'sys')
-rw-r--r--sys/uvm/uvm_mmap.c17
1 files changed, 11 insertions, 6 deletions
diff --git a/sys/uvm/uvm_mmap.c b/sys/uvm/uvm_mmap.c
index f08e9fc3b84..dd78690e878 100644
--- a/sys/uvm/uvm_mmap.c
+++ b/sys/uvm/uvm_mmap.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: uvm_mmap.c,v 1.162 2020/10/04 21:58:53 deraadt Exp $ */
+/* $OpenBSD: uvm_mmap.c,v 1.163 2020/10/07 12:26:20 mpi Exp $ */
/* $NetBSD: uvm_mmap.c,v 1.49 2001/02/18 21:19:08 chs Exp $ */
/*
@@ -288,8 +288,11 @@ sys_mmap(struct proc *p, void *v, register_t *retval)
/* check for file mappings (i.e. not anonymous) and verify file. */
if ((flags & MAP_ANON) == 0) {
- if ((fp = fd_getfile(fdp, fd)) == NULL)
- return (EBADF);
+ KERNEL_LOCK();
+ if ((fp = fd_getfile(fdp, fd)) == NULL) {
+ error = EBADF;
+ goto out;
+ }
if (fp->f_type != DTYPE_VNODE) {
error = ENODEV; /* only mmap vnodes! */
@@ -313,6 +316,7 @@ sys_mmap(struct proc *p, void *v, register_t *retval)
flags |= MAP_ANON;
FRELE(fp, p);
fp = NULL;
+ KERNEL_UNLOCK();
goto is_anon;
}
@@ -362,9 +366,7 @@ sys_mmap(struct proc *p, void *v, register_t *retval)
* EPERM.
*/
if (fp->f_flag & FWRITE) {
- KERNEL_LOCK();
error = VOP_GETATTR(vp, &va, p->p_ucred, p);
- KERNEL_UNLOCK();
if (error)
goto out;
if ((va.va_flags & (IMMUTABLE|APPEND)) == 0)
@@ -390,9 +392,9 @@ sys_mmap(struct proc *p, void *v, register_t *retval)
goto out;
}
}
- KERNEL_LOCK();
error = uvm_mmapfile(&p->p_vmspace->vm_map, &addr, size, prot,
maxprot, flags, vp, pos, lim_cur(RLIMIT_MEMLOCK), p);
+ FRELE(fp, p);
KERNEL_UNLOCK();
} else { /* MAP_ANON case */
if (fd != -1)
@@ -428,7 +430,10 @@ is_anon: /* label for SunOS style /dev/zero */
/* remember to add offset */
*retval = (register_t)(addr + pageoff);
+ return (error);
+
out:
+ KERNEL_UNLOCK();
if (fp)
FRELE(fp, p);
return (error);