Skip site navigation (1)Skip section navigation (2)
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 the


home | help

Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?6a66a5d2.25fde.773837f4>