svn commit: r308407 - head/sys/kern
Konstantin Belousov
kib at FreeBSD.org
Mon Nov 7 10:55:58 UTC 2016
Author: kib
Date: Mon Nov 7 10:55:56 2016
New Revision: 308407
URL: https://svnweb.freebsd.org/changeset/base/308407
Log:
vn_fullpath1() checked VV_ROOT and then unreferenced
vp->v_mount->mnt_vnodecovered unlocked. This allowed unmount to race.
Lock vnode after we noticed the VV_ROOT flag. See comments for
explanation why unlocked check for the flag is considered safe.
Reported and tested by: avg
Sponsored by: The FreeBSD Foundation
MFC after: 1 week
Modified:
head/sys/kern/vfs_cache.c
Modified: head/sys/kern/vfs_cache.c
==============================================================================
--- head/sys/kern/vfs_cache.c Mon Nov 7 10:54:56 2016 (r308406)
+++ head/sys/kern/vfs_cache.c Mon Nov 7 10:55:56 2016 (r308407)
@@ -2245,17 +2245,35 @@ vn_fullpath1(struct thread *td, struct v
slash_prefixed = 1;
}
while (vp != rdir && vp != rootvnode) {
- if (vp->v_vflag & VV_ROOT) {
- if (vp->v_iflag & VI_DOOMED) { /* forced unmount */
- vrele(vp);
+ /*
+ * The vp vnode must be already fully constructed,
+ * since it is either found in namecache or obtained
+ * from VOP_VPTOCNP(). We may test for VV_ROOT safely
+ * without obtaining the vnode lock.
+ */
+ if ((vp->v_vflag & VV_ROOT) != 0) {
+ vn_lock(vp, LK_RETRY | LK_SHARED);
+
+ /*
+ * With the vnode locked, check for races with
+ * unmount, forced or not. Note that we
+ * already verified that vp is not equal to
+ * the root vnode, which means that
+ * mnt_vnodecovered can be NULL only for the
+ * case of unmount.
+ */
+ if ((vp->v_iflag & VI_DOOMED) != 0 ||
+ (vp1 = vp->v_mount->mnt_vnodecovered) == NULL ||
+ vp1->v_mountedhere != vp->v_mount) {
+ vput(vp);
error = ENOENT;
SDT_PROBE3(vfs, namecache, fullpath, return,
error, vp, NULL);
break;
}
- vp1 = vp->v_mount->mnt_vnodecovered;
+
vref(vp1);
- vrele(vp);
+ vput(vp);
vp = vp1;
continue;
}
More information about the svn-src-all
mailing list