From 6e4e1c18e48602658a6472a40b9be7a818b05888 Mon Sep 17 00:00:00 2001 From: Pawel Jakub Dawidek Date: Tue, 21 Dec 2010 23:15:40 +0000 Subject: [PATCH] Use newly added NFSRV_FLAG_BUSY flag for nfsrv_fhtovp() to keep mount point busy. This fixes a race where we can pass invalid mount point to VFS_VGET() via vp->v_mount when exported file system was forcibly unmounted between nfsrv_fhtovp() and VFS_VGET(). Reviewed by: kib MFC after: 5 days --- sys/nfsserver/nfs_serv.c | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/sys/nfsserver/nfs_serv.c b/sys/nfsserver/nfs_serv.c index e30429126bf4..1fd704738771 100644 --- a/sys/nfsserver/nfs_serv.c +++ b/sys/nfsserver/nfs_serv.c @@ -3036,9 +3036,11 @@ nfsrv_readdirplus(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, int v3 = (nfsd->nd_flag & ND_NFSV3); int usevget = 1, vfslocked; struct componentname cn; + struct mount *mntp = NULL; nfsdbprintf(("%s %d\n", __FILE__, __LINE__)); vfslocked = 0; + vp_locked = 0; if (!v3) panic("nfsrv_readdirplus: v3 proc called on a v2 connection"); fhp = &nfh.fh_generic; @@ -3058,14 +3060,17 @@ nfsrv_readdirplus(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, if (siz > xfer) siz = xfer; fullsiz = siz; - error = nfsrv_fhtovp(fhp, 0, &vp, &vfslocked, nfsd, slp, - nam, &rdonly, TRUE); - vp_locked = 1; - if (!error && vp->v_type != VDIR) { - error = ENOTDIR; - vput(vp); - vp = NULL; - vp_locked = 0; + error = nfsrv_fhtovp(fhp, NFSRV_FLAG_BUSY, &vp, &vfslocked, nfsd, slp, + nam, &rdonly); + if (!error) { + vp_locked = 1; + mntp = vp->v_mount; + if (vp->v_type != VDIR) { + error = ENOTDIR; + vput(vp); + vp = NULL; + vp_locked = 0; + } } if (error) { nfsm_reply(NFSX_UNSIGNED); @@ -3207,8 +3212,8 @@ nfsrv_readdirplus(struct nfsrv_descript *nfsd, struct nfssvc_sock *slp, * For readdir_and_lookup get the vnode using * the file number. */ - error = VFS_VGET(vp->v_mount, dp->d_fileno, - LK_SHARED, &nvp); + error = VFS_VGET(mntp, dp->d_fileno, LK_SHARED, + &nvp); if (error != 0 && error != EOPNOTSUPP) { error = 0; goto invalid;