diff options
author | anton <anton@cvs.openbsd.org> | 2019-08-26 18:56:30 +0000 |
---|---|---|
committer | anton <anton@cvs.openbsd.org> | 2019-08-26 18:56:30 +0000 |
commit | 70a2f7d18ba0761a8e7fe20bb76d527f0e263eec (patch) | |
tree | 09aef6c3db24477402629fc3652e5898f9f4e1f9 /sys/kern/vfs_vops.c | |
parent | 55cc054a0127bed4a8be071ce5ebbede999753dc (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.c | 14 |
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)); } |