summaryrefslogtreecommitdiffstats
path: root/sys/kern/vfs_extattr.c
diff options
context:
space:
mode:
authorjeff <jeff@FreeBSD.org>2006-02-23 05:18:07 +0000
committerjeff <jeff@FreeBSD.org>2006-02-23 05:18:07 +0000
commitdc6bf4c70b11af03f2248f04cf5b88593709e3b2 (patch)
treef4cacdff42abbfc05f688fe2477274fa4ca3844a /sys/kern/vfs_extattr.c
parent63c47d3ba4ae5bc60372b5af574be6fb12f7eec0 (diff)
downloadFreeBSD-src-dc6bf4c70b11af03f2248f04cf5b88593709e3b2.zip
FreeBSD-src-dc6bf4c70b11af03f2248f04cf5b88593709e3b2.tar.gz
- Use vfs_ref/rel to protect a mountpoint from going away while VFS_STATFS
is being called. Be sure to grab the ref before we unlock the vnode to prevent the mount from disappearing. Tested by: kris
Diffstat (limited to 'sys/kern/vfs_extattr.c')
-rw-r--r--sys/kern/vfs_extattr.c39
1 files changed, 29 insertions, 10 deletions
diff --git a/sys/kern/vfs_extattr.c b/sys/kern/vfs_extattr.c
index e35d7c1..479c3de 100644
--- a/sys/kern/vfs_extattr.c
+++ b/sys/kern/vfs_extattr.c
@@ -249,19 +249,20 @@ kern_statfs(struct thread *td, char *path, enum uio_seg pathseg,
struct nameidata nd;
mtx_lock(&Giant);
- NDINIT(&nd, LOOKUP, FOLLOW | AUDITVNODE1, pathseg, path, td);
+ NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | AUDITVNODE1, pathseg, path, td);
error = namei(&nd);
if (error) {
mtx_unlock(&Giant);
return (error);
}
mp = nd.ni_vp->v_mount;
- sp = &mp->mnt_stat;
+ vfs_ref(mp);
NDFREE(&nd, NDF_ONLY_PNBUF);
- vrele(nd.ni_vp);
+ vput(nd.ni_vp);
#ifdef MAC
error = mac_check_mount_stat(td->td_ucred, mp);
if (error) {
+ vfs_rel(mp);
mtx_unlock(&Giant);
return (error);
}
@@ -269,10 +270,12 @@ kern_statfs(struct thread *td, char *path, enum uio_seg pathseg,
/*
* Set these in case the underlying filesystem fails to do so.
*/
+ sp = &mp->mnt_stat;
sp->f_version = STATFS_VERSION;
sp->f_namemax = NAME_MAX;
sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
error = VFS_STATFS(mp, sp, td);
+ vfs_rel(mp);
if (error) {
mtx_unlock(&Giant);
return (error);
@@ -327,32 +330,40 @@ kern_fstatfs(struct thread *td, int fd, struct statfs *buf)
error = getvnode(td->td_proc->p_fd, fd, &fp);
if (error)
return (error);
+ mtx_lock(&Giant);
vp = fp->f_vnode;
-#ifdef AUDIT
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
+#ifdef AUDIT
AUDIT_ARG(vnode, vp, ARG_VNODE1);
- VOP_UNLOCK(vp, 0, td);
#endif
mp = vp->v_mount;
+ if (mp)
+ vfs_ref(mp);
+ VOP_UNLOCK(vp, 0, td);
fdrop(fp, td);
- if (vp->v_iflag & VI_DOOMED)
+ if (vp->v_iflag & VI_DOOMED) {
+ if (mp)
+ vfs_rel(mp);
+ mtx_unlock(&Giant);
return (EBADF);
- mtx_lock(&Giant);
+ }
#ifdef MAC
error = mac_check_mount_stat(td->td_ucred, mp);
if (error) {
+ vfs_rel(mp);
mtx_unlock(&Giant);
return (error);
}
#endif
- sp = &mp->mnt_stat;
/*
* Set these in case the underlying filesystem fails to do so.
*/
+ sp = &mp->mnt_stat;
sp->f_version = STATFS_VERSION;
sp->f_namemax = NAME_MAX;
sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
error = VFS_STATFS(mp, sp, td);
+ vfs_rel(mp);
if (error) {
mtx_unlock(&Giant);
return (error);
@@ -4312,14 +4323,20 @@ kern_fhstatfs(struct thread *td, fhandle_t fh, struct statfs *buf)
return (error);
}
mp = vp->v_mount;
- sp = &mp->mnt_stat;
+ if (mp)
+ vfs_ref(mp);
vput(vp);
+ if (mp == NULL)
+ return (EBADF);
error = prison_canseemount(td->td_ucred, mp);
- if (error)
+ if (error) {
+ vfs_rel(mp);
return (error);
+ }
#ifdef MAC
error = mac_check_mount_stat(td->td_ucred, mp);
if (error) {
+ vfs_rel(mp);
mtx_unlock(&Giant);
return (error);
}
@@ -4327,10 +4344,12 @@ kern_fhstatfs(struct thread *td, fhandle_t fh, struct statfs *buf)
/*
* Set these in case the underlying filesystem fails to do so.
*/
+ sp = &mp->mnt_stat;
sp->f_version = STATFS_VERSION;
sp->f_namemax = NAME_MAX;
sp->f_flags = mp->mnt_flag & MNT_VISFLAGMASK;
error = VFS_STATFS(mp, sp, td);
+ vfs_rel(mp);
mtx_unlock(&Giant);
if (error)
return (error);
OpenPOWER on IntegriCloud