From 881a9516a2f7b50ea5cda69b23c4860b205396e7 Mon Sep 17 00:00:00 2001 From: Rick Macklem Date: Thu, 1 Nov 2018 15:27:22 +0000 Subject: [PATCH] Fix NFS client vnode locking to avoid a crash during forced dismount. A crash was reported where the crash occurred in nfs_advlock() when the NFS_ISV4(vp) macro was being executed. This was caused by the vnode being VI_DOOMED due to a forced dismount in progress. This patch fixes the problem by locking the vnode before executing the NFS_ISV4() macro. Tested by: rlibby PR: 232673 Reviewed by: kib MFC after: 2 weeks Differential Revision: https://reviews.freebsd.org/D17757 --- sys/fs/nfsclient/nfs_clvnops.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/sys/fs/nfsclient/nfs_clvnops.c b/sys/fs/nfsclient/nfs_clvnops.c index 056eb271eea6..47fd735d3b9e 100644 --- a/sys/fs/nfsclient/nfs_clvnops.c +++ b/sys/fs/nfsclient/nfs_clvnops.c @@ -3033,14 +3033,19 @@ nfs_advlock(struct vop_advlock_args *ap) int ret, error = EOPNOTSUPP; u_quad_t size; + ret = NFSVOPLOCK(vp, LK_SHARED); + if (ret != 0) + return (EBADF); if (NFS_ISV4(vp) && (ap->a_flags & (F_POSIX | F_FLOCK)) != 0) { - if (vp->v_type != VREG) + if (vp->v_type != VREG) { + NFSVOPUNLOCK(vp, 0); return (EINVAL); + } if ((ap->a_flags & F_POSIX) != 0) cred = p->p_ucred; else cred = td->td_ucred; - NFSVOPLOCK(vp, LK_EXCLUSIVE | LK_RETRY); + NFSVOPLOCK(vp, LK_UPGRADE | LK_RETRY); if (vp->v_iflag & VI_DOOMED) { NFSVOPUNLOCK(vp, 0); return (EBADF); @@ -3119,9 +3124,6 @@ nfs_advlock(struct vop_advlock_args *ap) NFSVOPUNLOCK(vp, 0); return (0); } else if (!NFS_ISV4(vp)) { - error = NFSVOPLOCK(vp, LK_SHARED); - if (error) - return (error); if ((VFSTONFS(vp->v_mount)->nm_flag & NFSMNT_NOLOCKD) != 0) { size = VTONFS(vp)->n_size; NFSVOPUNLOCK(vp, 0); @@ -3144,7 +3146,8 @@ nfs_advlock(struct vop_advlock_args *ap) NFSVOPUNLOCK(vp, 0); } } - } + } else + NFSVOPUNLOCK(vp, 0); return (error); }