From f8585b04c34eb5fee7afe974ed82443d515feb02 Mon Sep 17 00:00:00 2001
From: Dan McDonald <danmcd@joyent.com>
Date: Thu, 17 Oct 2019 14:17:15 -0400
Subject: [PATCH] Send zone's rootvp to untraverse()

---
 usr/src/uts/common/fs/nfs/nfs4_srv.c      | 20 ++++++++++++--------
 usr/src/uts/common/fs/nfs/nfs4_srv_attr.c |  2 +-
 usr/src/uts/common/fs/nfs/nfs4_srv_ns.c   |  8 +++-----
 usr/src/uts/common/fs/nfs/nfs_srv.c       |  9 +++++----
 usr/src/uts/common/nfs/export.h           |  2 +-
 5 files changed, 22 insertions(+), 19 deletions(-)

diff --git a/usr/src/uts/common/fs/nfs/nfs4_srv.c b/usr/src/uts/common/fs/nfs/nfs4_srv.c
index 66c28189dd..446f9fc070 100644
--- a/usr/src/uts/common/fs/nfs/nfs4_srv.c
+++ b/usr/src/uts/common/fs/nfs/nfs4_srv.c
@@ -973,25 +973,27 @@ do_rfs4_op_secinfo(struct compound_state *cs, char *nm, SECINFO4res *resp)
 	 * root of a filesystem, or above an export point.
 	 */
 	if (dotdot) {
-		ASSERT3U(exi->exi_zoneid, ==, curzone->zone_id);
+		vnode_t *zone_rootvp = ne->exi_root->exi_vp;
+
+		ASSERT3U(exi->exi_zoneid, ==, ne->exi_root->exi_zoneid);
 		/*
 		 * If dotdotting at the root of a filesystem, then
 		 * need to traverse back to the mounted-on filesystem
 		 * and do the dotdot lookup there.
 		 */
-		if ((dvp->v_flag & VROOT) || VN_IS_CURZONEROOT(dvp)) {
+		if ((dvp->v_flag & VROOT) || VN_CMP(dvp, zone_rootvp)) {
 
 			/*
 			 * If at the system root, then can
 			 * go up no further.
 			 */
-			if (VN_CMP(dvp, ZONE_ROOTVP()))
+			if (VN_CMP(dvp, zone_rootvp))
 				return (puterrno4(ENOENT));
 
 			/*
 			 * Traverse back to the mounted-on filesystem
 			 */
-			dvp = untraverse(dvp);
+			dvp = untraverse(dvp, zone_rootvp);
 
 			/*
 			 * Set the different_export flag so we remember
@@ -2719,26 +2721,28 @@ do_rfs4_op_lookup(char *nm, struct svc_req *req, struct compound_state *cs)
 	 * export point.
 	 */
 	if (dotdot) {
+		vnode_t *zone_rootvp;
+
 		ASSERT(cs->exi != NULL);
-		ASSERT3U(cs->exi->exi_zoneid, ==, curzone->zone_id);
+		zone_rootvp = cs->exi->exi_ne->exi_root->exi_vp;
 		/*
 		 * If dotdotting at the root of a filesystem, then
 		 * need to traverse back to the mounted-on filesystem
 		 * and do the dotdot lookup there.
 		 */
-		if ((cs->vp->v_flag & VROOT) || VN_IS_CURZONEROOT(cs->vp)) {
+		if ((cs->vp->v_flag & VROOT) || VN_CMP(cs->vp, zone_rootvp)) {
 
 			/*
 			 * If at the system root, then can
 			 * go up no further.
 			 */
-			if (VN_CMP(cs->vp, ZONE_ROOTVP()))
+			if (VN_CMP(cs->vp, zone_rootvp))
 				return (puterrno4(ENOENT));
 
 			/*
 			 * Traverse back to the mounted-on filesystem
 			 */
-			cs->vp = untraverse(cs->vp);
+			cs->vp = untraverse(cs->vp, zone_rootvp);
 
 			/*
 			 * Set the different_export flag so we remember
diff --git a/usr/src/uts/common/fs/nfs/nfs4_srv_attr.c b/usr/src/uts/common/fs/nfs/nfs4_srv_attr.c
index 8042732c86..242e2ab102 100644
--- a/usr/src/uts/common/fs/nfs/nfs4_srv_attr.c
+++ b/usr/src/uts/common/fs/nfs/nfs4_srv_attr.c
@@ -1320,7 +1320,7 @@ rfs4_get_mntdfileid(nfs4_attr_cmd_t cmd, struct nfs4_svgetit_arg *sarg)
 
 		/* extra hold for vp since untraverse might rele */
 		VN_HOLD(vp);
-		stubvp = untraverse(vp);
+		stubvp = untraverse(vp, ZONE_ROOTVP());
 
 		/*
 		 * If vp/stubvp are same, we must be at system-or-zone
diff --git a/usr/src/uts/common/fs/nfs/nfs4_srv_ns.c b/usr/src/uts/common/fs/nfs/nfs4_srv_ns.c
index 3501d0f0bb..920ebeca53 100644
--- a/usr/src/uts/common/fs/nfs/nfs4_srv_ns.c
+++ b/usr/src/uts/common/fs/nfs/nfs4_srv_ns.c
@@ -721,7 +721,7 @@ treeclimb_export(struct exportinfo *exip)
 			 * Traverse across the mountpoint and continue the
 			 * climb on the mounted-on filesystem.
 			 */
-			vp = untraverse(vp);
+			vp = untraverse(vp, ne->exi_root->exi_vp);
 			exportdir = 0;
 			continue;
 		}
@@ -910,17 +910,15 @@ treeclimb_unexport(nfs_export_t *ne, struct exportinfo *exip)
  * Traverse backward across mountpoint from the
  * root vnode of a filesystem to its mounted-on
  * vnode.
- *
- * Callers to this function have confirmed the use of curzone is safe here.
  */
 vnode_t *
-untraverse(vnode_t *vp)
+untraverse(vnode_t *vp, vnode_t *zone_rootvp)
 {
 	vnode_t *tvp, *nextvp;
 
 	tvp = vp;
 	for (;;) {
-		if (!(tvp->v_flag & VROOT) && !VN_IS_CURZONEROOT(tvp))
+		if (!(tvp->v_flag & VROOT) && !VN_CMP(tvp, zone_rootvp))
 			break;
 
 		/* lock vfs to prevent unmount of this vfs */
diff --git a/usr/src/uts/common/fs/nfs/nfs_srv.c b/usr/src/uts/common/fs/nfs/nfs_srv.c
index ac4acbd32d..0c996612a3 100644
--- a/usr/src/uts/common/fs/nfs/nfs_srv.c
+++ b/usr/src/uts/common/fs/nfs/nfs_srv.c
@@ -416,19 +416,20 @@ rfs_climb_crossmnt(vnode_t **dvpp, struct exportinfo **exip, cred_t *cr)
 {
 	struct exportinfo *exi;
 	vnode_t *dvp = *dvpp;
+	vnode_t *zone_rootvp;
 
-	ASSERT3U((*exip)->exi_zoneid, ==, curzone->zone_id);
-	ASSERT((dvp->v_flag & VROOT) || VN_IS_CURZONEROOT(dvp));
+	zone_rootvp = (*exip)->exi_ne->exi_root->exi_vp;
+	ASSERT((dvp->v_flag & VROOT) || VN_CMP(zone_rootvp, dvp));
 
 	VN_HOLD(dvp);
-	dvp = untraverse(dvp);
+	dvp = untraverse(dvp, zone_rootvp);
 	exi = nfs_vptoexi(NULL, dvp, cr, NULL, NULL, FALSE);
 	if (exi == NULL) {
 		VN_RELE(dvp);
 		return (-1);
 	}
 
-	ASSERT3U(exi->exi_zoneid, ==, curzone->zone_id);
+	ASSERT3U(exi->exi_zoneid, ==, (*exip)->exi_zoneid);
 	exi_rele(*exip);
 	*exip = exi;
 	VN_RELE(*dvpp);
diff --git a/usr/src/uts/common/nfs/export.h b/usr/src/uts/common/nfs/export.h
index dd8df1a67c..1ed93e28b9 100644
--- a/usr/src/uts/common/nfs/export.h
+++ b/usr/src/uts/common/nfs/export.h
@@ -651,7 +651,7 @@ extern struct exportinfo *nfs_vptoexi(vnode_t *, vnode_t *, cred_t *, int *,
     int *, bool_t);
 extern int	nfs_check_vpexi(vnode_t *, vnode_t *, cred_t *,
 			struct exportinfo **);
-extern vnode_t *untraverse(vnode_t *);
+extern vnode_t *untraverse(vnode_t *, vnode_t *);
 extern int	vn_is_nfs_reparse(vnode_t *, cred_t *);
 extern int	client_is_downrev(struct svc_req *);
 extern char    *build_symlink(vnode_t *, cred_t *, size_t *);
-- 
2.21.0 (Apple Git-122)

