git: 02b4a95522c9 - stable/15 - lookup: do not return vp_crossmp as dvp for mount over the reg file
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Mon, 27 Jul 2026 00:26:58 UTC
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