summaryrefslogtreecommitdiffstats
path: root/sys/kern/vfs_extattr.c
diff options
context:
space:
mode:
authortegge <tegge@FreeBSD.org>2000-08-09 01:57:11 +0000
committertegge <tegge@FreeBSD.org>2000-08-09 01:57:11 +0000
commit31d32eb7b17096bc631f7f00b1420754eac118b9 (patch)
treed301ee68a27508451a9155c0d2171300c23e8af0 /sys/kern/vfs_extattr.c
parent2eaedc55c80e3792597be951cb8634c86aef49b0 (diff)
downloadFreeBSD-src-31d32eb7b17096bc631f7f00b1420754eac118b9.zip
FreeBSD-src-31d32eb7b17096bc631f7f00b1420754eac118b9.tar.gz
Don't set flags on the mount structure before all permission checks have
been done. Don't allow multiple mount operations with MNT_UPDATE at the same time on the same mount point. When the first mount operation completed, MNT_UPDATE was cleared in the mount structure, causing the second to complete as if it was a no-update mount operation with the following bad side effects: - mount structure inserted multiple times onto the mountlist - vp->v_mountedhere incorrectly set, causing next namei operation walking into the mountpoint to crash with a locking against myself panic. Plug a vnode leak in case vinvalbuf fails.
Diffstat (limited to 'sys/kern/vfs_extattr.c')
-rw-r--r--sys/kern/vfs_extattr.c23
1 files changed, 19 insertions, 4 deletions
diff --git a/sys/kern/vfs_extattr.c b/sys/kern/vfs_extattr.c
index 3a15d64..9b68dd7 100644
--- a/sys/kern/vfs_extattr.c
+++ b/sys/kern/vfs_extattr.c
@@ -164,8 +164,6 @@ mount(p, uap)
vput(vp);
return (EOPNOTSUPP); /* Needs translation */
}
- mp->mnt_flag |= SCARG(uap, flags) &
- (MNT_RELOAD | MNT_FORCE | MNT_UPDATE | MNT_SNAPSHOT);
/*
* Only root, or the user that did the original mount is
* permitted to update it.
@@ -179,6 +177,18 @@ mount(p, uap)
vput(vp);
return (EBUSY);
}
+ simple_lock(&vp->v_interlock);
+ if ((vp->v_flag & VMOUNT) != 0 ||
+ vp->v_mountedhere != NULL) {
+ simple_unlock(&vp->v_interlock);
+ vfs_unbusy(mp, p);
+ vput(vp);
+ return (EBUSY);
+ }
+ vp->v_flag |= VMOUNT;
+ simple_unlock(&vp->v_interlock);
+ mp->mnt_flag |= SCARG(uap, flags) &
+ (MNT_RELOAD | MNT_FORCE | MNT_UPDATE | MNT_SNAPSHOT);
VOP_UNLOCK(vp, 0, p);
goto update;
}
@@ -192,8 +202,10 @@ mount(p, uap)
vput(vp);
return (error);
}
- if ((error = vinvalbuf(vp, V_SAVE, p->p_ucred, p, 0, 0)) != 0)
+ if ((error = vinvalbuf(vp, V_SAVE, p->p_ucred, p, 0, 0)) != 0) {
+ vput(vp);
return (error);
+ }
if (vp->v_type != VDIR) {
vput(vp);
return (ENOTDIR);
@@ -300,7 +312,6 @@ update:
*/
error = VFS_MOUNT(mp, SCARG(uap, path), SCARG(uap, data), &nd, p);
if (mp->mnt_flag & MNT_UPDATE) {
- vrele(vp);
if (mp->mnt_kern_flag & MNTK_WANTRDWR)
mp->mnt_flag &= ~MNT_RDONLY;
mp->mnt_flag &=~
@@ -319,6 +330,10 @@ update:
mp->mnt_syncer = NULL;
}
vfs_unbusy(mp, p);
+ simple_lock(&vp->v_interlock);
+ vp->v_flag &= ~VMOUNT;
+ simple_unlock(&vp->v_interlock);
+ vrele(vp);
return (error);
}
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, p);
OpenPOWER on IntegriCloud