summaryrefslogtreecommitdiffstats
path: root/sys/nfsserver
diff options
context:
space:
mode:
authorkib <kib@FreeBSD.org>2008-11-29 13:34:59 +0000
committerkib <kib@FreeBSD.org>2008-11-29 13:34:59 +0000
commitbf74bb2e167fcc7089b250309aa7131a27b672e2 (patch)
tree74a7c36a02638c961fd484be28f826c1acdb6a3a /sys/nfsserver
parent881f5f6bef889a5fc9f878e367245de363a1c55e (diff)
downloadFreeBSD-src-bf74bb2e167fcc7089b250309aa7131a27b672e2.zip
FreeBSD-src-bf74bb2e167fcc7089b250309aa7131a27b672e2.tar.gz
In the nfsrv_fhtovp(), after the vfs_getvfs() function found the pointer
to the fs, but before a vnode on the fs is locked, unmount may free fs structures, causing access to destroyed data and freed memory. Introduce a vfs_busymp() function that looks up and busies found fs while mountlist_mtx is held. Use it in nfsrv_fhtovp() and in the implementation of the handle syscalls. Two other uses of the vfs_getvfs() in the vfs_subr.c, namely in sysctl_vfs_ctl and vfs_getnewfsid seems to be ok. In particular, sysctl_vfs_ctl is protected by Giant by being a non-sleeping sysctl handler, that prevents Giant-locked unmount code to interfere with it. Noted by: tegge Reviewed by: dfr Tested by: pho MFC after: 1 month
Diffstat (limited to 'sys/nfsserver')
-rw-r--r--sys/nfsserver/nfs_srvsubs.c9
1 files changed, 6 insertions, 3 deletions
diff --git a/sys/nfsserver/nfs_srvsubs.c b/sys/nfsserver/nfs_srvsubs.c
index bc620214..49c6c16 100644
--- a/sys/nfsserver/nfs_srvsubs.c
+++ b/sys/nfsserver/nfs_srvsubs.c
@@ -1119,14 +1119,16 @@ nfsrv_fhtovp(fhandle_t *fhp, int lockflag, struct vnode **vpp, int *vfslockedp,
fhp = &nfs_pub.np_handle;
}
- mp = vfs_getvfs(&fhp->fh_fsid);
+ mp = vfs_busyfs(&fhp->fh_fsid);
if (!mp)
return (ESTALE);
vfslocked = VFS_LOCK_GIANT(mp);
error = VFS_CHECKEXP(mp, nam, &exflags, &credanon,
&numsecflavors, &secflavors);
- if (error)
+ if (error) {
+ vfs_unbusy(mp);
goto out;
+ }
if (numsecflavors == 0) {
/*
* This can happen if the system is running with an
@@ -1159,10 +1161,12 @@ nfsrv_fhtovp(fhandle_t *fhp, int lockflag, struct vnode **vpp, int *vfslockedp,
}
if (!mountreq) {
error = NFSERR_AUTHERR | AUTH_TOOWEAK;
+ vfs_unbusy(mp);
goto out;
}
}
error = VFS_FHTOVP(mp, &fhp->fh_fid, vpp);
+ vfs_unbusy(mp);
if (error)
goto out;
#ifdef MNT_EXNORESPORT
@@ -1196,7 +1200,6 @@ nfsrv_fhtovp(fhandle_t *fhp, int lockflag, struct vnode **vpp, int *vfslockedp,
if (!lockflag)
VOP_UNLOCK(*vpp, 0);
out:
- vfs_rel(mp);
if (error) {
VFS_UNLOCK_GIANT(vfslocked);
} else
OpenPOWER on IntegriCloud