diff options
author | anton <anton@cvs.openbsd.org> | 2019-07-22 16:39:30 +0000 |
---|---|---|
committer | anton <anton@cvs.openbsd.org> | 2019-07-22 16:39:30 +0000 |
commit | 32841a4b4eabaf2105a91cc17451ab9b6b21f8a3 (patch) | |
tree | 4b22d860ec6c3d5af86a3f7a63e073b4ec4eb215 /sys | |
parent | aa96e948e9d23ed4d6b600cae1adcb8ea50b639a (diff) |
Grab the vnode lock earlier in sys_getdents() since it could end up
sleeping, allowing the file offset to change. This is part of the
ongoing effort to protect the file offset using the vnode lock.
ok mpi@ visa@
Diffstat (limited to 'sys')
-rw-r--r-- | sys/kern/vfs_syscalls.c | 14 |
1 files changed, 9 insertions, 5 deletions
diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c index e2069c14329..f6a3f33cbdd 100644 --- a/sys/kern/vfs_syscalls.c +++ b/sys/kern/vfs_syscalls.c @@ -1,4 +1,4 @@ -/* $OpenBSD: vfs_syscalls.c,v 1.323 2019/07/15 15:05:21 beck Exp $ */ +/* $OpenBSD: vfs_syscalls.c,v 1.324 2019/07/22 16:39:29 anton Exp $ */ /* $NetBSD: vfs_syscalls.c,v 1.71 1996/04/23 10:29:02 mycroft Exp $ */ /* @@ -3011,15 +3011,20 @@ sys_getdents(struct proc *p, void *v, register_t *retval) error = EBADF; goto bad; } - if (fp->f_offset < 0) { + vp = fp->f_data; + if (vp->v_type != VDIR) { error = EINVAL; goto bad; } - vp = fp->f_data; - if (vp->v_type != VDIR) { + + vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); + + if (fp->f_offset < 0) { + VOP_UNLOCK(vp); error = EINVAL; goto bad; } + aiov.iov_base = SCARG(uap, buf); aiov.iov_len = buflen; auio.uio_iov = &aiov; @@ -3028,7 +3033,6 @@ sys_getdents(struct proc *p, void *v, register_t *retval) auio.uio_segflg = UIO_USERSPACE; auio.uio_procp = p; auio.uio_resid = buflen; - vn_lock(vp, LK_EXCLUSIVE | LK_RETRY); auio.uio_offset = fp->f_offset; error = VOP_READDIR(vp, &auio, fp->f_cred, &eofflag); fp->f_offset = auio.uio_offset; |