Date: Mon, 27 Jul 2026 00:26:58 +0000 From: Konstantin Belousov <kib@FreeBSD.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org Subject: git: 02b4a95522c9 - stable/15 - lookup: do not return vp_crossmp as dvp for mount over the reg file Message-ID: <6a66a5d2.25fde.773837f4@gitrepo.freebsd.org>
index | next in thread | raw e-mail
The branch stable/15 has been updated by kib: URL: https://cgit.FreeBSD.org/src/commit/?id=02b4a95522c9028a47dbe3571563cda72e115875 commit 02b4a95522c9028a47dbe3571563cda72e115875 Author: Konstantin Belousov <kib@FreeBSD.org> AuthorDate: 2026-07-12 11:56:13 +0000 Commit: Konstantin Belousov <kib@FreeBSD.org> CommitDate: 2026-07-27 00:26:15 +0000 lookup: do not return vp_crossmp as dvp for mount over the reg file (cherry picked from commit 29d1a3248a6da1ed9f1a46d7d525fb779306a90f) --- 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 addabb45e271..8d1d9cfff8aa 100644 --- a/sys/kern/vfs_lookup.c +++ b/sys/kern/vfs_lookup.c @@ -1483,15 +1483,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 769ebbcd18dc..a6f513b719ba 100644 --- a/sys/kern/vfs_syscalls.c +++ b/sys/kern/vfs_syscalls.c @@ -3821,6 +3821,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); @@ -3842,7 +3849,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?6a66a5d2.25fde.773837f4>
