summaryrefslogtreecommitdiff
path: root/sys/kern/vfs_vops.c
diff options
context:
space:
mode:
authoranton <anton@cvs.openbsd.org>2019-08-26 18:56:30 +0000
committeranton <anton@cvs.openbsd.org>2019-08-26 18:56:30 +0000
commit70a2f7d18ba0761a8e7fe20bb76d527f0e263eec (patch)
tree09aef6c3db24477402629fc3652e5898f9f4e1f9 /sys/kern/vfs_vops.c
parent55cc054a0127bed4a8be071ce5ebbede999753dc (diff)
When a thread tries to exclusively lock a vnode, the same thread must
ensure that any other thread currently trying to acquire the underlying vnode lock has observed that the same vnode is about to be exclusively locked. Such threads must then sleep until the exclusive lock has been released and then try to acquire the lock again. Otherwise, exclusive access to the vnode cannot be guaranteed. Thanks to naddy@ and visa@ for testing; ok visa@ Reported-by: syzbot+374d0e7e2400004957f7@syzkaller.appspotmail.com
Diffstat (limited to 'sys/kern/vfs_vops.c')
-rw-r--r--sys/kern/vfs_vops.c14
1 files changed, 13 insertions, 1 deletions
diff --git a/sys/kern/vfs_vops.c b/sys/kern/vfs_vops.c
index 9c39ab07705..e606c0b8af7 100644
--- a/sys/kern/vfs_vops.c
+++ b/sys/kern/vfs_vops.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: vfs_vops.c,v 1.21 2019/05/03 14:24:13 visa Exp $ */
+/* $OpenBSD: vfs_vops.c,v 1.22 2019/08/26 18:56:29 anton Exp $ */
/*
* Copyright (c) 2010 Thordur I. Bjornsson <thib@openbsd.org>
*
@@ -46,6 +46,7 @@
#include <sys/vnode.h>
#include <sys/unistd.h>
#include <sys/systm.h>
+#include <sys/lock.h> /* LK_DRAIN */
#ifdef VFSLCKDEBUG
#include <sys/systm.h> /* for panic() */
@@ -599,6 +600,17 @@ VOP_LOCK(struct vnode *vp, int flags)
if (vp->v_op->vop_lock == NULL)
return (EOPNOTSUPP);
+ if ((flags & LK_DRAIN) && vp->v_lockcount > 0) {
+ /*
+ * Ensure that any thread currently waiting on the same lock has
+ * observed that the vnode is about to be exclusively locked
+ * before continuing.
+ */
+ KASSERT(vp->v_flag & VXLOCK);
+ tsleep(&vp->v_lockcount, PINOD, "vop_lock", 0);
+ KASSERT(vp->v_lockcount == 0);
+ }
+
return ((vp->v_op->vop_lock)(&a));
}