The branch main has been updated by kib:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=d53633bfcf24a3eb3711e24b597aa8301f92b958

commit d53633bfcf24a3eb3711e24b597aa8301f92b958
Author:     Konstantin Belousov <[email protected]>
AuthorDate: 2026-06-04 19:56:36 +0000
Commit:     Konstantin Belousov <[email protected]>
CommitDate: 2026-06-06 03:28:28 +0000

    rename(2): do not allow to rename root vnode of the mounted filesystem
    
    Check for tdvp being vp_crossmp.  This cannot happen for the normal
    rename cases, but could if the target path specified by the syscall
    points to the nullfs mount over the regular file.  In this case namei()
    cannot step over crossmp, and keep it in ni_dvp.
    
    Since crossmp VOP_GETWRITEMOUNT() returns NULL mp, we retry the locking
    dance since the belief is that NULL return is transient.
    
    PR:     295826
    Reviewed by:    markj
    Tested by:      pho
    Sponsored by:   The FreeBSD Foundation
    MFC after:      1 week
    Differential revision:  https://reviews.freebsd.org/D57453
---
 sys/kern/vfs_lookup.c   | 2 +-
 sys/kern/vfs_syscalls.c | 9 +++++++++
 sys/sys/vnode.h         | 1 +
 3 files changed, 11 insertions(+), 1 deletion(-)

diff --git a/sys/kern/vfs_lookup.c b/sys/kern/vfs_lookup.c
index c1363c0104d3..5d66070ca142 100644
--- a/sys/kern/vfs_lookup.c
+++ b/sys/kern/vfs_lookup.c
@@ -113,7 +113,7 @@ SDT_PROBE_DEFINE4(vfs, namei, lookup, return, "int", 
"struct vnode *", "bool",
 uma_zone_t namei_zone;
 
 /* Placeholder vnode for mp traversal. */
-static struct vnode *vp_crossmp;
+struct vnode *vp_crossmp;
 
 static int
 crossmp_vop_islocked(struct vop_islocked_args *ap)
diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c
index 71d37e08c65b..7ca7ccd582e1 100644
--- a/sys/kern/vfs_syscalls.c
+++ b/sys/kern/vfs_syscalls.c
@@ -3823,6 +3823,15 @@ again:
        }
        tdvp = tond.ni_dvp;
        tvp = tond.ni_vp;
+       if (tdvp == vp_crossmp) {
+               /*
+                * Rename of the root vnode of the mounted
+                * filesystem. It is possible to get there with the
+                * nullfs mount over the regular file.
+                */
+               error = EBUSY;
+               goto out;
+       }
        if (tvp != NULL && (flags & AT_RENAME_NOREPLACE) != 0) {
                /*
                 * Often filesystems need to relock the vnodes in
diff --git a/sys/sys/vnode.h b/sys/sys/vnode.h
index 41b5e21fb879..99e90aa4187e 100644
--- a/sys/sys/vnode.h
+++ b/sys/sys/vnode.h
@@ -462,6 +462,7 @@ extern      struct mount *rootdevmp;        /* "/dev" mount 
*/
 extern u_long desiredvnodes;           /* number of vnodes desired */
 extern struct uma_zone *namei_zone;
 extern struct vattr va_null;           /* predefined null vattr structure */
+extern struct vnode *vp_crossmp;
 
 extern u_int vn_lock_pair_pause_max;
 

Reply via email to