git: 3bd0519d7485 - stable/13 - Revert "vfs_export: Add mnt_exjail to control exports done in prisons"

From: Rick Macklem <rmacklem_at_FreeBSD.org>
Date: Fri, 19 May 2023 21:39:43 UTC
The branch stable/13 has been updated by rmacklem:

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

commit 3bd0519d7485bb1ed4575887e13dbcd5db8f0592
Author:     Rick Macklem <rmacklem@FreeBSD.org>
AuthorDate: 2023-05-19 21:38:20 +0000
Commit:     Rick Macklem <rmacklem@FreeBSD.org>
CommitDate: 2023-05-19 21:38:20 +0000

    Revert "vfs_export: Add mnt_exjail to control exports done in prisons"
    
    Revert this commit until I can figure out build issue.
    
    This reverts commit 202d52261b92abdfb1ec39564ee1be3812bcdf92.
---
 sys/fs/nfsserver/nfs_nfsdport.c |  24 ++----
 sys/kern/kern_jail.c            |   1 -
 sys/kern/vfs_export.c           | 164 +---------------------------------------
 sys/kern/vfs_mount.c            |   9 +--
 sys/sys/jail.h                  |   3 +-
 sys/sys/mount.h                 |   5 +-
 6 files changed, 14 insertions(+), 192 deletions(-)

diff --git a/sys/fs/nfsserver/nfs_nfsdport.c b/sys/fs/nfsserver/nfs_nfsdport.c
index 50d3aa57c4aa..4247177a3fc0 100644
--- a/sys/fs/nfsserver/nfs_nfsdport.c
+++ b/sys/fs/nfsserver/nfs_nfsdport.c
@@ -3270,16 +3270,8 @@ nfsvno_checkexp(struct mount *mp, struct sockaddr *nam, struct nfsexstuff *exp,
 {
 	int error;
 
-	error = 0;
-	*credp = NULL;
-	MNT_ILOCK(mp);
-	if (mp->mnt_exjail == NULL ||
-	    mp->mnt_exjail->cr_prison != curthread->td_ucred->cr_prison)
-		error = EACCES;
-	MNT_IUNLOCK(mp);
-	if (error == 0)
-		error = VFS_CHECKEXP(mp, nam, &exp->nes_exflag, credp,
-		    &exp->nes_numsecflavor, exp->nes_secflavors);
+	error = VFS_CHECKEXP(mp, nam, &exp->nes_exflag, credp,
+	    &exp->nes_numsecflavor, exp->nes_secflavors);
 	if (error) {
 		if (NFSD_VNET(nfs_rootfhset)) {
 			exp->nes_exflag = 0;
@@ -3313,14 +3305,8 @@ nfsvno_fhtovp(struct mount *mp, fhandle_t *fhp, struct sockaddr *nam,
 		/* Make sure the server replies ESTALE to the client. */
 		error = ESTALE;
 	if (nam && !error) {
-		MNT_ILOCK(mp);
-		if (mp->mnt_exjail == NULL ||
-		    mp->mnt_exjail->cr_prison != curthread->td_ucred->cr_prison)
-			error = EACCES;
-		MNT_IUNLOCK(mp);
-		if (error == 0)
-			error = VFS_CHECKEXP(mp, nam, &exp->nes_exflag, credp,
-			    &exp->nes_numsecflavor, exp->nes_secflavors);
+		error = VFS_CHECKEXP(mp, nam, &exp->nes_exflag, credp,
+		    &exp->nes_numsecflavor, exp->nes_secflavors);
 		if (error) {
 			if (NFSD_VNET(nfs_rootfhset)) {
 				exp->nes_exflag = 0;
@@ -3490,7 +3476,7 @@ nfsrv_v4rootexport(void *argp, struct ucred *cred, struct thread *p)
 	struct nameidata nd;
 	fhandle_t fh;
 
-	error = vfs_export(NFSD_VNET(nfsv4root_mnt), &nfsexargp->export, false);
+	error = vfs_export(NFSD_VNET(nfsv4root_mnt), &nfsexargp->export);
 	if ((nfsexargp->export.ex_flags & MNT_DELEXPORT) != 0)
 		NFSD_VNET(nfs_rootfhset) = 0;
 	else if (error == 0) {
diff --git a/sys/kern/kern_jail.c b/sys/kern/kern_jail.c
index 0203dcd0faf1..622b9f6c7cb9 100644
--- a/sys/kern/kern_jail.c
+++ b/sys/kern/kern_jail.c
@@ -3035,7 +3035,6 @@ prison_cleanup(struct prison *pr)
 {
 	sx_assert(&allprison_lock, SA_XLOCKED);
 	mtx_assert(&pr->pr_mtx, MA_NOTOWNED);
-	vfs_exjail_delete(pr);
 	shm_remove_prison(pr);
 	(void)osd_jail_call(pr, PR_METHOD_REMOVE, NULL);
 }
diff --git a/sys/kern/vfs_export.c b/sys/kern/vfs_export.c
index 16d2e88bdc41..cab37ce205ad 100644
--- a/sys/kern/vfs_export.c
+++ b/sys/kern/vfs_export.c
@@ -52,7 +52,6 @@ __FBSDID("$FreeBSD$");
 #include <sys/mbuf.h>
 #include <sys/mount.h>
 #include <sys/mutex.h>
-#include <sys/proc.h>
 #include <sys/rmlock.h>
 #include <sys/refcount.h>
 #include <sys/signalvar.h>
@@ -297,18 +296,12 @@ vfs_free_addrlist(struct netexport *nep)
  * and the passed in netexport.
  * Struct export_args *argp is the variable used to twiddle options,
  * the structure is described in sys/mount.h
- * The do_exjail argument should be true if *mp is in the mountlist
- * and false if not.  It is not in the mountlist for the NFSv4 rootfs
- * fake mount point just used for exports.
  */
 int
-vfs_export(struct mount *mp, struct export_args *argp, bool do_exjail)
+vfs_export(struct mount *mp, struct export_args *argp)
 {
 	struct netexport *nep;
-	struct ucred *cr;
-	struct prison *pr;
 	int error;
-	bool new_nep;
 
 	if ((argp->ex_flags & (MNT_DELEXPORT | MNT_EXPORTED)) == 0)
 		return (EINVAL);
@@ -319,7 +312,6 @@ vfs_export(struct mount *mp, struct export_args *argp, bool do_exjail)
 		return (EINVAL);
 
 	error = 0;
-	pr = curthread->td_ucred->cr_prison;
 	lockmgr(&mp->mnt_explock, LK_EXCLUSIVE, NULL);
 	nep = mp->mnt_export;
 	if (argp->ex_flags & MNT_DELEXPORT) {
@@ -327,21 +319,6 @@ vfs_export(struct mount *mp, struct export_args *argp, bool do_exjail)
 			error = ENOENT;
 			goto out;
 		}
-		MNT_ILOCK(mp);
-		if (mp->mnt_exjail != NULL && mp->mnt_exjail->cr_prison != pr &&
-		    pr == &prison0) {
-			MNT_IUNLOCK(mp);
-			/* EXDEV will not get logged by mountd(8). */
-			error = EXDEV;
-			goto out;
-		} else if (mp->mnt_exjail != NULL &&
-		    mp->mnt_exjail->cr_prison != pr) {
-			MNT_IUNLOCK(mp);
-			/* EPERM will get logged by mountd(8). */
-			error = EPERM;
-			goto out;
-		}
-		MNT_IUNLOCK(mp);
 		if (mp->mnt_flag & MNT_EXPUBLIC) {
 			vfs_setpublicfs(NULL, NULL, NULL);
 			MNT_ILOCK(mp);
@@ -353,51 +330,18 @@ vfs_export(struct mount *mp, struct export_args *argp, bool do_exjail)
 		free(nep, M_MOUNT);
 		nep = NULL;
 		MNT_ILOCK(mp);
-		cr = mp->mnt_exjail;
-		mp->mnt_exjail = NULL;
 		mp->mnt_flag &= ~(MNT_EXPORTED | MNT_DEFEXPORTED);
 		MNT_IUNLOCK(mp);
-		if (cr != NULL) {
-			atomic_subtract_int(&pr->pr_exportcnt, 1);
-			crfree(cr);
-		}
 	}
 	if (argp->ex_flags & MNT_EXPORTED) {
-		new_nep = false;
-		MNT_ILOCK(mp);
-		if (mp->mnt_exjail == NULL) {
-			MNT_IUNLOCK(mp);
-			if (do_exjail && nep != NULL) {
-				vfs_free_addrlist(nep);
-				memset(nep, 0, sizeof(*nep));
-				new_nep = true;
-			}
-		} else if (mp->mnt_exjail->cr_prison != pr) {
-			MNT_IUNLOCK(mp);
-			error = EPERM;
-			goto out;
-		} else
-			MNT_IUNLOCK(mp);
 		if (nep == NULL) {
-			nep = malloc(sizeof(struct netexport), M_MOUNT,
-			    M_WAITOK | M_ZERO);
+			nep = malloc(sizeof(struct netexport), M_MOUNT, M_WAITOK | M_ZERO);
 			mp->mnt_export = nep;
-			new_nep = true;
 		}
 		if (argp->ex_flags & MNT_EXPUBLIC) {
-			if ((error = vfs_setpublicfs(mp, nep, argp)) != 0) {
-				if (new_nep) {
-					mp->mnt_export = NULL;
-					free(nep, M_MOUNT);
-				}
+			if ((error = vfs_setpublicfs(mp, nep, argp)) != 0)
 				goto out;
-			}
-			new_nep = false;
 			MNT_ILOCK(mp);
-			if (do_exjail && mp->mnt_exjail == NULL) {
-				mp->mnt_exjail = crhold(curthread->td_ucred);
-				atomic_add_int(&pr->pr_exportcnt, 1);
-			}
 			mp->mnt_flag |= MNT_EXPUBLIC;
 			MNT_IUNLOCK(mp);
 		}
@@ -405,18 +349,9 @@ vfs_export(struct mount *mp, struct export_args *argp, bool do_exjail)
 			argp->ex_numsecflavors = 1;
 			argp->ex_secflavors[0] = AUTH_SYS;
 		}
-		if ((error = vfs_hang_addrlist(mp, nep, argp))) {
-			if (new_nep) {
-				mp->mnt_export = NULL;
-				free(nep, M_MOUNT);
-			}
+		if ((error = vfs_hang_addrlist(mp, nep, argp)))
 			goto out;
-		}
 		MNT_ILOCK(mp);
-		if (do_exjail && mp->mnt_exjail == NULL) {
-			mp->mnt_exjail = crhold(curthread->td_ucred);
-			atomic_add_int(&pr->pr_exportcnt, 1);
-		}
 		mp->mnt_flag |= MNT_EXPORTED;
 		MNT_IUNLOCK(mp);
 	}
@@ -436,97 +371,6 @@ out:
 	return (error);
 }
 
-/*
- * Get rid of credential references for this prison.
- */
-void
-vfs_exjail_delete(struct prison *pr)
-{
-	struct mount *mp;
-	struct ucred *cr;
-	int error, i;
-
-	/*
-	 * Since this function is called from prison_cleanup() after
-	 * all processes in the prison have exited, the value of
-	 * pr_exportcnt can no longer increase.  It is possible for
-	 * a dismount of a file system exported within this prison
-	 * to be in progress.  In this case, the file system is no
-	 * longer in the mountlist and the mnt_exjail will be free'd
-	 * by vfs_mount_destroy() at some time.  As such, pr_exportcnt
-	 * and, therefore "i", is the upper bound on the number of
-	 * mnt_exjail entries to be found by this function.
-	 */
-	i = atomic_load_int(&pr->pr_exportcnt);
-	KASSERT(i >= 0, ("vfs_exjail_delete: pr_exportcnt negative"));
-	if (i == 0)
-		return;
-	mtx_lock(&mountlist_mtx);
-tryagain:
-	TAILQ_FOREACH(mp, &mountlist, mnt_list) {
-		MNT_ILOCK(mp);
-		if (mp->mnt_exjail != NULL &&
-		    mp->mnt_exjail->cr_prison == pr) {
-			MNT_IUNLOCK(mp);
-			error = vfs_busy(mp, MBF_MNTLSTLOCK | MBF_NOWAIT);
-			if (error != 0) {
-				/*
-				 * If the vfs_busy() fails, we still want to
-				 * get rid of mnt_exjail for two reasons:
-				 * - a credential reference will result in
-				 *   a prison not being removed
-				 * - setting mnt_exjail NULL indicates that
-				 *   the exports are no longer valid
-				 * The now invalid exports will be deleted
-				 * when the file system is dismounted or
-				 * the file system is re-exported by mountd.
-				 */
-				cr = NULL;
-				MNT_ILOCK(mp);
-				if (mp->mnt_exjail != NULL &&
-				    mp->mnt_exjail->cr_prison == pr) {
-					cr = mp->mnt_exjail;
-					mp->mnt_exjail = NULL;
-				}
-				MNT_IUNLOCK(mp);
-				if (cr != NULL) {
-					crfree(cr);
-					i--;
-				}
-				if (i == 0)
-					break;
-				continue;
-			}
-			cr = NULL;
-			lockmgr(&mp->mnt_explock, LK_EXCLUSIVE, NULL);
-			MNT_ILOCK(mp);
-			if (mp->mnt_exjail != NULL &&
-			    mp->mnt_exjail->cr_prison == pr) {
-				cr = mp->mnt_exjail;
-				mp->mnt_exjail = NULL;
-				mp->mnt_flag &= ~(MNT_EXPORTED | MNT_DEFEXPORTED);
-				MNT_IUNLOCK(mp);
-				vfs_free_addrlist(mp->mnt_export);
-				free(mp->mnt_export, M_MOUNT);
-				mp->mnt_export = NULL;
-			} else
-				MNT_IUNLOCK(mp);
-			lockmgr(&mp->mnt_explock, LK_RELEASE, NULL);
-			if (cr != NULL) {
-				crfree(cr);
-				i--;
-			}
-			mtx_lock(&mountlist_mtx);
-			vfs_unbusy(mp);
-			if (i == 0)
-				break;
-			goto tryagain;
-		}
-		MNT_IUNLOCK(mp);
-	}
-	mtx_unlock(&mountlist_mtx);
-}
-
 /*
  * Set the publicly exported filesystem (WebNFS). Currently, only
  * one public filesystem is possible in the spec (RFC 2054 and 2055)
diff --git a/sys/kern/vfs_mount.c b/sys/kern/vfs_mount.c
index 4c941c2616ff..d5b137e7ffab 100644
--- a/sys/kern/vfs_mount.c
+++ b/sys/kern/vfs_mount.c
@@ -618,11 +618,6 @@ vfs_mount_destroy(struct mount *mp)
 #endif
 	if (mp->mnt_opt != NULL)
 		vfs_freeopts(mp->mnt_opt);
-	if (mp->mnt_exjail != NULL) {
-		atomic_subtract_int(&mp->mnt_exjail->cr_prison->pr_exportcnt,
-		    1);
-		crfree(mp->mnt_exjail);
-	}
 	if (mp->mnt_export != NULL) {
 		vfs_free_addrlist(mp->mnt_export);
 		free(mp->mnt_export, M_MOUNT);
@@ -1241,7 +1236,7 @@ vfs_domount_update(
 			} else
 				export_error = EINVAL;
 			if (export_error == 0)
-				export_error = vfs_export(mp, &export, true);
+				export_error = vfs_export(mp, &export);
 			free(export.ex_groups, M_TEMP);
 			break;
 		case (sizeof(export)):
@@ -1263,7 +1258,7 @@ vfs_domount_update(
 			else
 				export_error = EINVAL;
 			if (export_error == 0)
-				export_error = vfs_export(mp, &export, true);
+				export_error = vfs_export(mp, &export);
 			free(grps, M_TEMP);
 			break;
 		default:
diff --git a/sys/sys/jail.h b/sys/sys/jail.h
index e81b272677bb..f4d4e521d7de 100644
--- a/sys/sys/jail.h
+++ b/sys/sys/jail.h
@@ -190,8 +190,7 @@ struct prison {
 	int		 pr_enforce_statfs;		/* (p) statfs permission */
 	int		 pr_devfs_rsnum;		/* (p) devfs ruleset */
 	enum prison_state pr_state;			/* (q) state in life cycle */
-	volatile int	 pr_exportcnt;			/* (r) count of mount exports */
-	int		 pr_spare;
+	int		 pr_spare[2];
 	int		 pr_osreldate;			/* (c) kern.osreldate value */
 	unsigned long	 pr_hostid;			/* (p) jail hostid */
 	char		 pr_name[MAXHOSTNAMELEN];	/* (p) admin jail name */
diff --git a/sys/sys/mount.h b/sys/sys/mount.h
index 382be23e37e5..9a69240ddba5 100644
--- a/sys/sys/mount.h
+++ b/sys/sys/mount.h
@@ -222,7 +222,7 @@ struct mount {
 	int		mnt_writeopcount;	/* (i) write syscalls pending */
 	struct vfsoptlist *mnt_opt;		/* current mount options */
 	struct vfsoptlist *mnt_optnew;		/* new options passed to fs */
-	struct ucred	*mnt_exjail;		/* (i) jail which did exports */
+	u_int		mnt_pad0;		/* was mnt_maxsymlinklen */
 	struct statfs	mnt_stat;		/* cache of filesystem stats */
 	struct ucred	*mnt_cred;		/* credentials of mounter */
 	void *		mnt_data;		/* private data */
@@ -985,9 +985,8 @@ int	vfs_setpublicfs			    /* set publicly exported fs */
 	    (struct mount *, struct netexport *, struct export_args *);
 void	vfs_periodic(struct mount *, int);
 int	vfs_busy(struct mount *, int);
-void	vfs_exjail_delete(struct prison *);
 int	vfs_export			 /* process mount export info */
-	    (struct mount *, struct export_args *, bool);
+	    (struct mount *, struct export_args *);
 void	vfs_free_addrlist(struct netexport *);
 void	vfs_allocate_syncvnode(struct mount *);
 void	vfs_deallocate_syncvnode(struct mount *);