git: 6fa205a6233f - main - nullfs: add nounixbypass mount option

From: Konstantin Belousov <kib_at_FreeBSD.org>
Date: Thu, 09 Oct 2025 23:02:20 UTC
The branch main has been updated by kib:

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

commit 6fa205a6233fea7c41ba0306c778bc5cab37ce7d
Author:     Konstantin Belousov <kib@FreeBSD.org>
AuthorDate: 2025-10-08 15:47:15 +0000
Commit:     Konstantin Belousov <kib@FreeBSD.org>
CommitDate: 2025-10-09 22:47:36 +0000

    nullfs: add nounixbypass mount option
    
    The option, when set, disables bypassing the unix socket vnode down
    to the lower mp, effectively preventing connection to nullfs unix
    socket from being acceptable from the lower mp (and vice versa).
    
    This is done by providing a vop vector that stops bypass for unp-related
    VOPs.  I believe that VFS_VOP_VECTOR_REGISTER() does the right thing
    there regardless of the order of initialization.
    
    Reviewed by:    markj
    Sponsored by:   The FreeBSD Foundation
    MFC after:      1 week
    Differential revision:  https://reviews.freebsd.org/D52983
---
 sys/fs/nullfs/null.h        | 3 ++-
 sys/fs/nullfs/null_subr.c   | 4 +++-
 sys/fs/nullfs/null_vfsops.c | 9 +++++++++
 sys/fs/nullfs/null_vnops.c  | 8 ++++++++
 4 files changed, 22 insertions(+), 2 deletions(-)

diff --git a/sys/fs/nullfs/null.h b/sys/fs/nullfs/null.h
index 17fd90203174..7bfdc20a3f67 100644
--- a/sys/fs/nullfs/null.h
+++ b/sys/fs/nullfs/null.h
@@ -39,6 +39,7 @@
 #include <vm/uma.h>
 
 #define	NULLM_CACHE		0x0001
+#define	NULLM_NOUNPBYPASS	0x0002
 
 struct null_mount {
 	struct mount	*nullm_vfs;
@@ -90,7 +91,7 @@ null_is_nullfs_vnode(struct vnode *vp)
 	const struct vop_vector *op;
 
 	op = vp->v_op;
-	return (op == &null_vnodeops);
+	return (op == &null_vnodeops || op == &null_vnodeops_no_unp_bypass);
 }
 
 extern uma_zone_t null_node_zone;
diff --git a/sys/fs/nullfs/null_subr.c b/sys/fs/nullfs/null_subr.c
index d7f847d449d0..a843ae44f121 100644
--- a/sys/fs/nullfs/null_subr.c
+++ b/sys/fs/nullfs/null_subr.c
@@ -240,7 +240,9 @@ null_nodeget(struct mount *mp, struct vnode *lowervp, struct vnode **vpp)
 	 */
 	xp = uma_zalloc_smr(null_node_zone, M_WAITOK);
 
-	error = getnewvnode("nullfs", mp, &null_vnodeops, &vp);
+	error = getnewvnode("nullfs", mp, (MOUNTTONULLMOUNT(mp)->nullm_flags &
+	    NULLM_NOUNPBYPASS) != 0 ? &null_vnodeops_no_unp_bypass :
+	    &null_vnodeops, &vp);
 	if (error) {
 		vput(lowervp);
 		uma_zfree_smr(null_node_zone, xp);
diff --git a/sys/fs/nullfs/null_vfsops.c b/sys/fs/nullfs/null_vfsops.c
index 483d4182e65e..170a3dd51cd8 100644
--- a/sys/fs/nullfs/null_vfsops.c
+++ b/sys/fs/nullfs/null_vfsops.c
@@ -87,6 +87,8 @@ nullfs_mount(struct mount *mp)
 	bool isvnunlocked;
 	static const char cache_opt_name[] = "cache";
 	static const char nocache_opt_name[] = "nocache";
+	static const char unixbypass_opt_name[] = "unixbypass";
+	static const char nounixbypass_opt_name[] = "nounixbypass";
 
 	NULLFSDEBUG("nullfs_mount(mp = %p)\n", (void *)mp);
 
@@ -222,6 +224,13 @@ nullfs_mount(struct mount *mp)
 		    &xmp->notify_node);
 	}
 
+	if (vfs_getopt(mp->mnt_optnew, unixbypass_opt_name, NULL, NULL) == 0) {
+		;
+	} else if (vfs_getopt(mp->mnt_optnew, nounixbypass_opt_name, NULL,
+	    NULL) == 0) {
+		xmp->nullm_flags |= NULLM_NOUNPBYPASS;
+	}
+
 	if (lowerrootvp == mp->mnt_vnodecovered) {
 		vn_lock(lowerrootvp, LK_EXCLUSIVE | LK_RETRY | LK_CANRECURSE);
 		lowerrootvp->v_vflag |= VV_CROSSLOCK;
diff --git a/sys/fs/nullfs/null_vnops.c b/sys/fs/nullfs/null_vnops.c
index 4b9342f43870..d4baabeb40ab 100644
--- a/sys/fs/nullfs/null_vnops.c
+++ b/sys/fs/nullfs/null_vnops.c
@@ -1256,3 +1256,11 @@ struct vop_vector null_vnodeops = {
 	.vop_copy_file_range =	VOP_PANIC,
 };
 VFS_VOP_VECTOR_REGISTER(null_vnodeops);
+
+struct vop_vector null_vnodeops_no_unp_bypass = {
+	.vop_default =		&null_vnodeops,
+	.vop_unp_bind =		vop_stdunp_bind,
+	.vop_unp_connect =	vop_stdunp_connect,
+	.vop_unp_detach =	vop_stdunp_detach,
+};
+VFS_VOP_VECTOR_REGISTER(null_vnodeops_no_unp_bypass);