diff options
author | kib <kib@FreeBSD.org> | 2008-11-29 13:34:59 +0000 |
---|---|---|
committer | kib <kib@FreeBSD.org> | 2008-11-29 13:34:59 +0000 |
commit | bf74bb2e167fcc7089b250309aa7131a27b672e2 (patch) | |
tree | 74a7c36a02638c961fd484be28f826c1acdb6a3a /sys/kern/vfs_subr.c | |
parent | 881f5f6bef889a5fc9f878e367245de363a1c55e (diff) | |
download | FreeBSD-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/kern/vfs_subr.c')
-rw-r--r-- | sys/kern/vfs_subr.c | 26 |
1 files changed, 26 insertions, 0 deletions
diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c index 32093c0..16373b1 100644 --- a/sys/kern/vfs_subr.c +++ b/sys/kern/vfs_subr.c @@ -407,6 +407,32 @@ vfs_getvfs(fsid_t *fsid) } /* + * Lookup a mount point by filesystem identifier, busying it before + * returning. + */ +struct mount * +vfs_busyfs(fsid_t *fsid) +{ + struct mount *mp; + int error; + + mtx_lock(&mountlist_mtx); + TAILQ_FOREACH(mp, &mountlist, mnt_list) { + if (mp->mnt_stat.f_fsid.val[0] == fsid->val[0] && + mp->mnt_stat.f_fsid.val[1] == fsid->val[1]) { + error = vfs_busy(mp, MBF_MNTLSTLOCK); + if (error) { + mtx_unlock(&mountlist_mtx); + return (NULL); + } + return (mp); + } + } + mtx_unlock(&mountlist_mtx); + return ((struct mount *) 0); +} + +/* * Check if a user can access privileged mount options. */ int |