diff options
author | Martin Pieuchot <mpi@cvs.openbsd.org> | 2020-10-07 12:26:21 +0000 |
---|---|---|
committer | Martin Pieuchot <mpi@cvs.openbsd.org> | 2020-10-07 12:26:21 +0000 |
commit | 0afe36204da3fa27fa61053c0f447b62e39fc14c (patch) | |
tree | 107ea21c11444b7567d1b49e194ad2487aaebfad /sys | |
parent | dcb3de7f094fdccd130e961a883263400c9108e5 (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.c | 17 |
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); |