Date: Mon, 20 Jul 2026 21:55:46 +0000 From: Konstantin Belousov <kib@FreeBSD.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org Subject: git: 29d1a3248a6d - main - lookup: do not return vp_crossmp as dvp for mount over the reg file Message-ID: <6a5e9962.24375.7eb6d7a0@gitrepo.freebsd.org>
index | next in thread | raw e-mail
The branch main has been updated by kib: URL: https://cgit.FreeBSD.org/src/commit/?id=29d1a3248a6da1ed9f1a46d7d525fb779306a90f commit 29d1a3248a6da1ed9f1a46d7d525fb779306a90f Author: Konstantin Belousov <kib@FreeBSD.org> AuthorDate: 2026-07-12 11:56:13 +0000 Commit: Konstantin Belousov <kib@FreeBSD.org> CommitDate: 2026-07-20 21:55:39 +0000 lookup: do not return vp_crossmp as dvp for mount over the reg file Return the covered vnode instead. Tested by: pho Sponsored by: The FreeBSD Foundation MFC after: 1 week Differential revision: https://reviews.freebsd.org/D58191 --- sys/kern/vfs_lookup.c | 34 ++++++++++++++++++++++++++++++---- sys/kern/vfs_syscalls.c | 9 ++++++++- 2 files changed, 38 insertions(+), 5 deletions(-) diff --git a/sys/kern/vfs_lookup.c b/sys/kern/vfs_lookup.c index 5d66070ca142..57b536eab6ea 100644 --- a/sys/kern/vfs_lookup.c +++ b/sys/kern/vfs_lookup.c @@ -1487,15 +1487,41 @@ nextname: error = EROFS; goto bad2; } - if (!wantparent) { + if (wantparent) { + /* + * Do not return vp_crossmp for the case of mount + * over the regular file. Substitute ni_dvp with the + * covered vnode. + */ + if (ndp->ni_dvp == vp_crossmp && + (dp->v_vflag & VV_ROOT) != 0 && dp->v_type != VDIR) { + struct vnode *mvp; + + vput(ndp->ni_dvp); + mvp = dp->v_mount->mnt_vnodecovered; + vref(mvp); + ndp->ni_dvp = mvp; + if ((cnp->cn_flags & LOCKPARENT) != 0) { + vn_lock_pair(dp, true, VOP_ISLOCKED(dp), mvp, + false, LK_EXCLUSIVE); + if (VN_IS_DOOMED(dp) || VN_IS_DOOMED(mvp)) { + error = ENOENT; + goto bad2; + } + } else { + ni_dvp_unlocked = 1; + } + } else if ((cnp->cn_flags & LOCKPARENT) == 0 && + ndp->ni_dvp != dp) { + VOP_UNLOCK(ndp->ni_dvp); + ni_dvp_unlocked = 1; + } + } else { ni_dvp_unlocked = 2; if (ndp->ni_dvp != dp) vput(ndp->ni_dvp); else vrele(ndp->ni_dvp); - } else if ((cnp->cn_flags & LOCKPARENT) == 0 && ndp->ni_dvp != dp) { - VOP_UNLOCK(ndp->ni_dvp); - ni_dvp_unlocked = 1; } if (cnp->cn_flags & AUDITVNODE1) diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c index 29d503bbb3fa..eeee67418877 100644 --- a/sys/kern/vfs_syscalls.c +++ b/sys/kern/vfs_syscalls.c @@ -3819,6 +3819,13 @@ again: } #endif fvp = fromnd.ni_vp; + if (fromnd.ni_dvp->v_type != VDIR) { + NDFREE_PNBUF(&fromnd); + vrele(fromnd.ni_dvp); + if (fvp != NULL) + vrele(fromnd.ni_vp); + return (EBUSY); + } if (exchange && fvp == NULL) { NDFREE_PNBUF(&fromnd); vrele(fromnd.ni_dvp); @@ -3840,7 +3847,7 @@ again: } tdvp = tond.ni_dvp; tvp = tond.ni_vp; - if (tdvp == vp_crossmp) { + if (tdvp->v_type != VDIR) { /* * Rename of the root vnode of the mounted * filesystem. It is possible to get there with thehome | help
Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?6a5e9962.24375.7eb6d7a0>
