summaryrefslogtreecommitdiff
path: root/sys/kern/vfs_syscalls.c
diff options
context:
space:
mode:
authoranton <anton@cvs.openbsd.org>2019-07-22 16:39:30 +0000
committeranton <anton@cvs.openbsd.org>2019-07-22 16:39:30 +0000
commit32841a4b4eabaf2105a91cc17451ab9b6b21f8a3 (patch)
tree4b22d860ec6c3d5af86a3f7a63e073b4ec4eb215 /sys/kern/vfs_syscalls.c
parentaa96e948e9d23ed4d6b600cae1adcb8ea50b639a (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/kern/vfs_syscalls.c')
-rw-r--r--sys/kern/vfs_syscalls.c14
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;