Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 22 Aug 2020 22:56:50 +0000 (UTC)
From:      Rick Macklem <rmacklem@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-projects@freebsd.org
Subject:   svn commit: r364496 - in projects/nfs-over-tls: sys/fs/nfs sys/fs/nfsserver sys/sys usr.sbin/mountd
Message-ID:  <202008222256.07MMuoZZ007827@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: rmacklem
Date: Sat Aug 22 22:56:50 2020
New Revision: 364496
URL: https://svnweb.freebsd.org/changeset/base/364496

Log:
  Update mount.h to use high order bits of the 64bit mnt_flags and merge
  recent changes to mountd.c.

Modified:
  projects/nfs-over-tls/sys/fs/nfs/nfsdport.h
  projects/nfs-over-tls/sys/fs/nfsserver/nfs_nfsdport.c
  projects/nfs-over-tls/sys/sys/mount.h
  projects/nfs-over-tls/usr.sbin/mountd/mountd.c

Modified: projects/nfs-over-tls/sys/fs/nfs/nfsdport.h
==============================================================================
--- projects/nfs-over-tls/sys/fs/nfs/nfsdport.h	Sat Aug 22 21:32:11 2020	(r364495)
+++ projects/nfs-over-tls/sys/fs/nfs/nfsdport.h	Sat Aug 22 22:56:50 2020	(r364496)
@@ -81,9 +81,9 @@ struct nfsexstuff {
 #define	NFSVNO_EXPORTANON(e)		((e)->nes_exflag & MNT_EXPORTANON)
 #define	NFSVNO_EXSTRICTACCESS(e)	((e)->nes_exflag & MNT_EXSTRICTACCESS)
 #define	NFSVNO_EXV4ONLY(e)		((e)->nes_exflag & MNT_EXV4ONLY)
-#define	NFSVNO_EXTLS(e)			((e)->nes_exflag & MNTEX_TLS)
-#define	NFSVNO_EXTLSCERT(e)		((e)->nes_exflag & MNTEX_TLSCERT)
-#define	NFSVNO_EXTLSCERTUSER(e)		((e)->nes_exflag & MNTEX_TLSCERTUSER)
+#define	NFSVNO_EXTLS(e)			((e)->nes_exflag & MNT_EXTLS)
+#define	NFSVNO_EXTLSCERT(e)		((e)->nes_exflag & MNT_EXTLSCERT)
+#define	NFSVNO_EXTLSCERTUSER(e)		((e)->nes_exflag & MNT_EXTLSCERTUSER)
 
 #define	NFSVNO_SETEXRDONLY(e)	((e)->nes_exflag = (MNT_EXPORTED|MNT_EXRDONLY))
 

Modified: projects/nfs-over-tls/sys/fs/nfsserver/nfs_nfsdport.c
==============================================================================
--- projects/nfs-over-tls/sys/fs/nfsserver/nfs_nfsdport.c	Sat Aug 22 21:32:11 2020	(r364495)
+++ projects/nfs-over-tls/sys/fs/nfsserver/nfs_nfsdport.c	Sat Aug 22 22:56:50 2020	(r364496)
@@ -3561,11 +3561,11 @@ nfsvno_v4rootexport(struct nfsrv_descript *nd)
 	}
 
 	/* And set ND_EXxx flags for TLS. */
-	if ((exflags & MNTEX_TLS) != 0) {
+	if ((exflags & MNT_EXTLS) != 0) {
 		nd->nd_flag |= ND_EXTLS;
-		if ((exflags & MNTEX_TLSCERT) != 0)
+		if ((exflags & MNT_EXTLSCERT) != 0)
 			nd->nd_flag |= ND_EXTLSCERT;
-		if ((exflags & MNTEX_TLSCERTUSER) != 0)
+		if ((exflags & MNT_EXTLSCERTUSER) != 0)
 			nd->nd_flag |= ND_EXTLSCERTUSER;
 	}
 

Modified: projects/nfs-over-tls/sys/sys/mount.h
==============================================================================
--- projects/nfs-over-tls/sys/sys/mount.h	Sat Aug 22 21:32:11 2020	(r364495)
+++ projects/nfs-over-tls/sys/sys/mount.h	Sat Aug 22 22:56:50 2020	(r364496)
@@ -294,6 +294,45 @@ void          __mnt_vnode_markerfree_lazy(struct vnode
 
 #endif /* _KERNEL */
 
+#if defined(_WANT_MNTOPTNAMES) || defined(_KERNEL)
+struct mntoptnames {
+	uint64_t o_opt;
+	const char *o_name;
+};
+#define MNTOPT_NAMES							\
+	{ MNT_ASYNC,		"asynchronous" },			\
+	{ MNT_EXPORTED,		"NFS exported" },			\
+	{ MNT_LOCAL,		"local" },				\
+	{ MNT_NOATIME,		"noatime" },				\
+	{ MNT_NOEXEC,		"noexec" },				\
+	{ MNT_NOSUID,		"nosuid" },				\
+	{ MNT_NOSYMFOLLOW,	"nosymfollow" },			\
+	{ MNT_QUOTA,		"with quotas" },			\
+	{ MNT_RDONLY,		"read-only" },				\
+	{ MNT_SYNCHRONOUS,	"synchronous" },			\
+	{ MNT_UNION,		"union" },				\
+	{ MNT_NOCLUSTERR,	"noclusterr" },				\
+	{ MNT_NOCLUSTERW,	"noclusterw" },				\
+	{ MNT_SUIDDIR,		"suiddir" },				\
+	{ MNT_SOFTDEP,		"soft-updates" },			\
+	{ MNT_SUJ,		"journaled soft-updates" },		\
+	{ MNT_MULTILABEL,	"multilabel" },				\
+	{ MNT_ACLS,		"acls" },				\
+	{ MNT_NFS4ACLS,		"nfsv4acls" },				\
+	{ MNT_GJOURNAL,		"gjournal" },				\
+	{ MNT_AUTOMOUNTED,	"automounted" },			\
+	{ MNT_VERIFIED,		"verified" },				\
+	{ MNT_UNTRUSTED,	"untrusted" },				\
+	{ MNT_NOCOVER,		"nocover" },				\
+	{ MNT_EMPTYDIR,		"emptydir" },				\
+	{ MNT_UPDATE,		"update" },				\
+	{ MNT_DELEXPORT,	"delexport" },				\
+	{ MNT_RELOAD,		"reload" },				\
+	{ MNT_FORCE,		"force" },				\
+	{ MNT_SNAPSHOT,		"snapshot" },				\
+	{ 0, NULL }
+#endif
+
 /*
  * User specifiable flags, stored in mnt_flag.
  */
@@ -326,6 +365,9 @@ void          __mnt_vnode_markerfree_lazy(struct vnode
 #define	MNT_EXPORTANON	0x0000000000000400ULL	/* anon uid mapping for all */
 #define	MNT_EXKERB	0x0000000000000800ULL	/* exported with Kerberos */
 #define	MNT_EXPUBLIC	0x0000000020000000ULL	/* public export (WebNFS) */
+#define	MNT_EXTLS	0x0000004000000000ULL /* require TLS */
+#define	MNT_EXTLSCERT	0x0000008000000000ULL /* require TLS with client cert */
+#define	MNT_EXTLSCERTUSER 0x0000010000000000ULL /* require TLS with user cert */
 
 /*
  * Flags set by internal operations,
@@ -364,23 +406,6 @@ void          __mnt_vnode_markerfree_lazy(struct vnode
 			MNT_NOCLUSTERR	| MNT_NOCLUSTERW | MNT_SUIDDIR	| \
 			MNT_ACLS	| MNT_USER	| MNT_NFS4ACLS	| \
 			MNT_AUTOMOUNTED | MNT_UNTRUSTED)
-
-/*
- * Export flags that are only set/used in the ex_flags field and
- * not in mnt_flag.  Since some are defined as MNT_EXxxx above,
- * these ones are just redefined here.
- * MNT_EXPORTED must remain and be set/cleared in mnt_flag.
- * The others defined as MNT_xxx should probably remain for
- * compatibility with old versions of mountd, etc.
- */
-#define	MNTEX_TLS		0x0000000000000001ULL	/* TLS RPC required */
-#define	MNTEX_TLSCERT		0x0000000000000002ULL	/* verified cert req */
-#define	MNTEX_TLSCERTUSER	0x0000000000000004ULL	/* user cert req */
-#define	MNTEX_EXPORTED		MNT_EXPORTED		/* filesystem exported */
-#define	MNTEX_RDONLY		MNT_EXRDONLY		/* exported read only */
-#define	MNTEX_EXPORTANON	MNT_EXPORTANON		/* anon uid mapping for all */
-#define	MNTEX_KERB		MNT_EXKERB		/* exported with Kerberos */
-#define	MNTEX_PUBLIC		MNT_EXPUBLIC		/* public export (WebNFS) */
 
 /*
  * External filesystem command modifier flags.

Modified: projects/nfs-over-tls/usr.sbin/mountd/mountd.c
==============================================================================
--- projects/nfs-over-tls/usr.sbin/mountd/mountd.c	Sat Aug 22 21:32:11 2020	(r364495)
+++ projects/nfs-over-tls/usr.sbin/mountd/mountd.c	Sat Aug 22 22:56:50 2020	(r364496)
@@ -48,6 +48,7 @@ static char sccsid[] = "@(#)mountd.c	8.15 (Berkeley) 5
 __FBSDID("$FreeBSD$");
 
 #include <sys/param.h>
+#include <sys/conf.h>
 #include <sys/fcntl.h>
 #include <sys/fnv_hash.h>
 #include <sys/linker.h>
@@ -112,6 +113,15 @@ struct dirlist {
 #define	DP_DEFSET	0x1
 #define DP_HOSTSET	0x2
 
+/*
+ * maproot/mapall credentials.
+ */
+struct expcred {
+	uid_t		cr_uid;
+	int		cr_ngroups;
+	gid_t		cr_groups[NGROUPS_MAX + 1];
+};
+
 struct exportlist {
 	struct dirlist	*ex_dirl;
 	struct dirlist	*ex_defdir;
@@ -120,8 +130,8 @@ struct exportlist {
 	fsid_t		ex_fs;
 	char		*ex_fsdir;
 	char		*ex_indexfile;
-	struct xucred	ex_defanon;
-	int		ex_defexflags;
+	struct expcred	ex_defanon;
+	uint64_t	ex_defexflags;
 	int		ex_numsecflavors;
 	int		ex_secflavors[MAXSECFLAVORS];
 	int		ex_defnumsecflavors;
@@ -152,8 +162,8 @@ struct grouplist {
 	int gr_type;
 	union grouptypes gr_ptr;
 	struct grouplist *gr_next;
-	struct xucred gr_anon;
-	int gr_exflags;
+	struct expcred gr_anon;
+	uint64_t gr_exflags;
 	int gr_flag;
 	int gr_numsecflavors;
 	int gr_secflavors[MAXSECFLAVORS];
@@ -184,11 +194,17 @@ struct fhreturn {
 
 #define	GETPORT_MAXTRY	20	/* Max tries to get a port # */
 
+/*
+ * How long to delay a reload of exports when there are RPC request(s)
+ * to process, in usec.  Must be less than 1second.
+ */
+#define	RELOADDELAY	250000
+
 /* Global defs */
 static char	*add_expdir(struct dirlist **, char *, int);
 static void	add_dlist(struct dirlist **, struct dirlist *,
 		    struct grouplist *, int, struct exportlist *,
-		    struct xucred *, int);
+		    struct expcred *, uint64_t);
 static void	add_mlist(char *, char *);
 static int	check_dirpath(char *);
 static int	check_options(struct dirlist *);
@@ -202,10 +218,10 @@ static void	clearout_service(void);
 static void	del_mlist(char *hostp, char *dirp);
 static struct dirlist	*dirp_search(struct dirlist *, char *);
 static int	do_export_mount(struct exportlist *, struct statfs *);
-static int	do_mount(struct exportlist *, struct grouplist *, int,
-		    struct xucred *, char *, int, struct statfs *, int, int *);
+static int	do_mount(struct exportlist *, struct grouplist *, uint64_t,
+		    struct expcred *, char *, int, struct statfs *, int, int *);
 static int	do_opt(char **, char **, struct exportlist *,
-		    struct grouplist *, int *, int *, struct xucred *);
+		    struct grouplist *, int *, uint64_t *, struct expcred *);
 static struct exportlist	*ex_search(fsid_t *, struct exportlisthead *);
 static struct exportlist	*get_exp(void);
 static void	free_dir(struct dirlist *);
@@ -220,7 +236,7 @@ static void	free_exports(struct exportlisthead *);
 static void	read_exportfile(int);
 static int	compare_nmount_exportlist(struct iovec *, int, char *);
 static int	compare_export(struct exportlist *, struct exportlist *);
-static int	compare_cred(struct xucred *, struct xucred *);
+static int	compare_cred(struct expcred *, struct expcred *);
 static int	compare_secflavor(int *, int *, int);
 static void	delete_export(struct iovec *, int, struct statfs *, char *);
 static int	get_host(char *, struct grouplist *, struct grouplist *);
@@ -231,13 +247,13 @@ static int	get_net(char *, struct netmsk *, int);
 static void	getexp_err(struct exportlist *, struct grouplist *, const char *);
 static struct grouplist	*get_grp(void);
 static void	hang_dirp(struct dirlist *, struct grouplist *,
-		    struct exportlist *, int, struct xucred *, int);
+		    struct exportlist *, int, struct expcred *, uint64_t);
 static void	huphandler(int sig);
 static int	makemask(struct sockaddr_storage *ssp, int bitlen);
 static void	mntsrv(struct svc_req *, SVCXPRT *);
 static void	nextfield(char **, char **);
 static void	out_of_mem(void);
-static void	parsecred(char *, struct xucred *);
+static void	parsecred(char *, struct expcred *);
 static int	parsesec(char *, struct exportlist *);
 static int	put_exlist(struct dirlist *, XDR *, struct dirlist *,
 		    int *, int);
@@ -253,6 +269,7 @@ static int	xdr_explist_common(XDR *, caddr_t, int);
 static int	xdr_fhs(XDR *, caddr_t);
 static int	xdr_mlist(XDR *, caddr_t);
 static void	terminate(int);
+static void	cp_cred(struct expcred *, struct expcred *);
 
 #define	EXPHASH(f)	(fnv_32_buf((f), sizeof(fsid_t), 0) % exphashsize)
 static struct exportlisthead *exphead = NULL;
@@ -262,13 +279,6 @@ static SLIST_HEAD(, mountlist) mlhead = SLIST_HEAD_INI
 static char *exnames_default[2] = { _PATH_EXPORTS, NULL };
 static char **exnames;
 static char **hosts = NULL;
-static struct xucred def_anon = {
-	XUCRED_VERSION,
-	(uid_t)65534,
-	1,
-	{ (gid_t)65533 },
-	{ NULL }
-};
 static int force_v2 = 0;
 static int resvport_only = 1;
 static int nhosts = 0;
@@ -410,6 +420,10 @@ main(int argc, char **argv)
 	int maxrec = RPC_MAXDATASIZE;
 	int attempt_cnt, port_len, port_pos, ret;
 	char **port_list;
+	uint64_t curtime, nexttime;
+	struct timeval tv;
+	struct timespec tp;
+	sigset_t sighup_mask;
 
 	/* Check that another mountd isn't already running. */
 	pfh = pidfile_open(_PATH_MOUNTDPID, 0600, &otherpid);
@@ -665,19 +679,49 @@ main(int argc, char **argv)
 	}
 
 	/* Expand svc_run() here so that we can call get_exportlist(). */
+	curtime = nexttime = 0;
+	sigemptyset(&sighup_mask);
+	sigaddset(&sighup_mask, SIGHUP);
 	for (;;) {
-		if (got_sighup) {
-			get_exportlist(1);
+		clock_gettime(CLOCK_MONOTONIC, &tp);
+		curtime = tp.tv_sec;
+		curtime = curtime * 1000000 + tp.tv_nsec / 1000;
+		sigprocmask(SIG_BLOCK, &sighup_mask, NULL);
+		if (got_sighup && curtime >= nexttime) {
 			got_sighup = 0;
-		}
+			sigprocmask(SIG_UNBLOCK, &sighup_mask, NULL);
+			get_exportlist(1);
+			clock_gettime(CLOCK_MONOTONIC, &tp);
+			nexttime = tp.tv_sec;
+			nexttime = nexttime * 1000000 + tp.tv_nsec / 1000 +
+			    RELOADDELAY;
+		} else
+			sigprocmask(SIG_UNBLOCK, &sighup_mask, NULL);
+
+		/*
+		 * If a reload is pending, poll for received request(s),
+		 * otherwise set a RELOADDELAY timeout, since a SIGHUP
+		 * could be processed between the got_sighup test and
+		 * the select() system call.
+		 */
+		tv.tv_sec = 0;
+		if (got_sighup)
+			tv.tv_usec = 0;
+		else
+			tv.tv_usec = RELOADDELAY;
 		readfds = svc_fdset;
-		switch (select(svc_maxfd + 1, &readfds, NULL, NULL, NULL)) {
+		switch (select(svc_maxfd + 1, &readfds, NULL, NULL, &tv)) {
 		case -1:
-			if (errno == EINTR)
-                                continue;
+			if (errno == EINTR) {
+				/* Allow a reload now. */
+				nexttime = 0;
+				continue;
+			}
 			syslog(LOG_ERR, "mountd died: select: %m");
 			exit(1);
 		case 0:
+			/* Allow a reload now. */
+			nexttime = 0;
 			continue;
 		default:
 			svc_getreqset(&readfds);
@@ -1047,7 +1091,8 @@ mntsrv(struct svc_req *rqstp, SVCXPRT *transp)
 	struct sockaddr *saddr;
 	u_short sport;
 	char rpcpath[MNTPATHLEN + 1], dirpath[MAXPATHLEN];
-	int bad = 0, defset, hostset;
+	int defset, hostset;
+	long bad = 0;
 	sigset_t sighup_mask;
 	int numsecflavors, *secflavorsp;
 
@@ -1463,9 +1508,10 @@ get_exportlist_one(int passno)
 	struct grouplist *grp, *tgrp, *savgrp;
 	struct dirlist *dirhead;
 	struct statfs fsb;
-	struct xucred anon;
+	struct expcred anon;
 	char *cp, *endcp, *dirp, *hst, *usr, *dom, savedc;
-	int len, has_host, exflags, got_nondir, dirplen, netgrp;
+	int len, has_host, got_nondir, dirplen, netgrp;
+	uint64_t exflags;
 
 	v4root_phase = 0;
 	dirhead = (struct dirlist *)NULL;
@@ -1481,8 +1527,10 @@ get_exportlist_one(int passno)
 		 * Set defaults.
 		 */
 		has_host = FALSE;
-		anon = def_anon;
-		exflags = MNTEX_EXPORTED;
+		anon.cr_uid = UID_NOBODY;
+		anon.cr_ngroups = 1;
+		anon.cr_groups[0] = GID_NOGROUP;
+		exflags = MNT_EXPORTED;
 		got_nondir = 0;
 		opt_flags = 0;
 		ep = (struct exportlist *)NULL;
@@ -1568,10 +1616,8 @@ get_exportlist_one(int passno)
 				    ep = get_exp();
 				} else {
 				    if (ep) {
-					if (ep->ex_fs.val[0] !=
-					    fsb.f_fsid.val[0] ||
-					    ep->ex_fs.val[1] !=
-					    fsb.f_fsid.val[1]) {
+					if (fsidcmp(&ep->ex_fs, &fsb.f_fsid)
+					    != 0) {
 						getexp_err(ep, tgrp,
 						    "fsid mismatch");
 						goto nextline;
@@ -1700,7 +1746,7 @@ get_exportlist_one(int passno)
 		grp = tgrp;
 		do {
 			grp->gr_exflags = exflags;
-			grp->gr_anon = anon;
+			cp_cred(&grp->gr_anon, &anon);
 			if (v4root_phase == 2 && passno == 0)
 				LOGDEBUG("do_mount v4root");
 			if (passno == 0 && do_mount(ep, grp, exflags, &anon,
@@ -1840,7 +1886,7 @@ get_exportlist(int passno)
 	 */
 	bzero(&eargs, sizeof (eargs));
 	eargs.export.ex_flags = MNT_DELEXPORT;
-	if (nfssvc(NFSSVC_V4ROOTEXPORT, (caddr_t)&eargs) < 0 &&
+	if (nfssvc(NFSSVC_V4ROOTEXPORT | NFSSVC_NEWSTRUCT, (caddr_t)&eargs) < 0 &&
 	    errno != ENOENT)
 		syslog(LOG_ERR, "Can't delete exports for V4:");
 
@@ -1868,7 +1914,7 @@ get_exportlist(int passno)
 		LOGDEBUG("doing passno=0");
 		/*
 		 * Clear flag that notes if a public fh has been exported.
-		 * It is set by do_mount() if MNTEX_PUBLIC is set for the entry.
+		 * It is set by do_mount() if MNT_EXPUBLIC is set for the entry.
 		 */
 		has_publicfh = 0;
 
@@ -2088,8 +2134,7 @@ compare_nmount_exportlist(struct iovec *iov, int iovle
 			if ((oep->ex_flag & EX_DONE) == 0) {
 				LOGDEBUG("not done delete=%s", oep->ex_fsdir);
 				if (statfs(oep->ex_fsdir, &ofs) >= 0 &&
-				    oep->ex_fs.val[0] == ofs.f_fsid.val[0] &&
-				    oep->ex_fs.val[1] == ofs.f_fsid.val[1]) {
+				    fsidcmp(&oep->ex_fs, &ofs.f_fsid) == 0) {
 					LOGDEBUG("do delete");
 					/*
 					 * Clear has_publicfh if if was set
@@ -2220,10 +2265,10 @@ compare_export(struct exportlist *ep, struct exportlis
 	} while (0)
 
 /*
- * Compare to struct xucred's.  Return 0 if the same and 1 otherwise.
+ * Compare two struct expcred's.  Return 0 if the same and 1 otherwise.
  */
 static int
-compare_cred(struct xucred *cr0, struct xucred *cr1)
+compare_cred(struct expcred *cr0, struct expcred *cr1)
 {
 
 	if (cr0->cr_uid != cr1->cr_uid || cr0->cr_ngroups != cr1->cr_ngroups)
@@ -2353,8 +2398,7 @@ ex_search(fsid_t *fsid, struct exportlisthead *exhp)
 
 	i = EXPHASH(fsid);
 	SLIST_FOREACH(ep, &exhp[i], entries) {
-		if (ep->ex_fs.val[0] == fsid->val[0] &&
-		    ep->ex_fs.val[1] == fsid->val[1])
+		if (fsidcmp(&ep->ex_fs, fsid) == 0)
 			return (ep);
 	}
 
@@ -2389,7 +2433,7 @@ add_expdir(struct dirlist **dpp, char *cp, int len)
  */
 static void
 hang_dirp(struct dirlist *dp, struct grouplist *grp, struct exportlist *ep,
-	int flags, struct xucred *anoncrp, int exflags)
+	int flags, struct expcred *anoncrp, uint64_t exflags)
 {
 	struct hostlist *hp;
 	struct dirlist *dp2;
@@ -2407,7 +2451,7 @@ hang_dirp(struct dirlist *dp, struct grouplist *grp, s
 			if (ep->ex_numsecflavors > 0)
 				memcpy(ep->ex_defsecflavors, ep->ex_secflavors,
 				    sizeof(ep->ex_secflavors));
-			ep->ex_defanon = *anoncrp;
+			cp_cred(&ep->ex_defanon, anoncrp);
 			ep->ex_defexflags = exflags;
 		} else while (grp) {
 			hp = get_ht();
@@ -2441,7 +2485,8 @@ hang_dirp(struct dirlist *dp, struct grouplist *grp, s
  */
 static void
 add_dlist(struct dirlist **dpp, struct dirlist *newdp, struct grouplist *grp,
-	int flags, struct exportlist *ep, struct xucred *anoncrp, int exflags)
+	int flags, struct exportlist *ep, struct expcred *anoncrp,
+	uint64_t exflags)
 {
 	struct dirlist *dp;
 	struct hostlist *hp;
@@ -2490,7 +2535,7 @@ add_dlist(struct dirlist **dpp, struct dirlist *newdp,
 		if (ep->ex_numsecflavors > 0)
 			memcpy(ep->ex_defsecflavors, ep->ex_secflavors,
 			    sizeof(ep->ex_secflavors));
-		ep->ex_defanon = *anoncrp;
+		cp_cred(&ep->ex_defanon, anoncrp);
 		ep->ex_defexflags = exflags;
 	}
 }
@@ -2662,7 +2707,7 @@ parsesec(char *seclist, struct exportlist *ep)
  */
 static int
 do_opt(char **cpp, char **endcpp, struct exportlist *ep, struct grouplist *grp,
-	int *has_hostp, int *exflagsp, struct xucred *cr)
+	int *has_hostp, uint64_t *exflagsp, struct expcred *cr)
 {
 	char *cpoptarg, *cpoptend;
 	char *cp, *endcp, *cpopt, savedc, savedc2;
@@ -2697,14 +2742,14 @@ do_opt(char **cpp, char **endcpp, struct exportlist *e
 			}
 		}
 		if (!strcmp(cpopt, "ro") || !strcmp(cpopt, "o")) {
-			*exflagsp |= MNTEX_RDONLY;
+			*exflagsp |= MNT_EXRDONLY;
 		} else if (cpoptarg && (!strcmp(cpopt, "maproot") ||
 		    !(allflag = strcmp(cpopt, "mapall")) ||
 		    !strcmp(cpopt, "root") || !strcmp(cpopt, "r"))) {
 			usedarg++;
 			parsecred(cpoptarg, cr);
 			if (allflag == 0) {
-				*exflagsp |= MNTEX_EXPORTANON;
+				*exflagsp |= MNT_EXPORTANON;
 				opt_flags |= OP_MAPALL;
 			} else
 				opt_flags |= OP_MAPROOT;
@@ -2737,9 +2782,9 @@ do_opt(char **cpp, char **endcpp, struct exportlist *e
 		} else if (!strcmp(cpopt, "alldirs")) {
 			opt_flags |= OP_ALLDIRS;
 		} else if (!strcmp(cpopt, "public")) {
-			*exflagsp |= MNTEX_PUBLIC;
+			*exflagsp |= MNT_EXPUBLIC;
 		} else if (!strcmp(cpopt, "webnfs")) {
-			*exflagsp |= (MNTEX_PUBLIC|MNTEX_RDONLY|MNTEX_EXPORTANON);
+			*exflagsp |= (MNT_EXPUBLIC|MNT_EXRDONLY|MNT_EXPORTANON);
 			opt_flags |= OP_MAPALL;
 		} else if (cpoptarg && !strcmp(cpopt, "index")) {
 			ep->ex_indexfile = strdup(cpoptarg);
@@ -2751,11 +2796,12 @@ do_opt(char **cpp, char **endcpp, struct exportlist *e
 			opt_flags |= OP_SEC;
 			usedarg++;
 		} else if (!strcmp(cpopt, "tls")) {
-			*exflagsp |= MNTEX_TLS;
+			*exflagsp |= MNT_EXTLS;
 		} else if (!strcmp(cpopt, "tlscert")) {
-			*exflagsp |= (MNTEX_TLS | MNTEX_TLSCERT);
+			*exflagsp |= (MNT_EXTLS | MNT_EXTLSCERT);
 		} else if (!strcmp(cpopt, "tlscertuser")) {
-			*exflagsp |= (MNTEX_TLS | MNTEX_TLSCERT | MNTEX_TLSCERTUSER);
+			*exflagsp |= (MNT_EXTLS | MNT_EXTLSCERT |
+			    MNT_EXTLSCERTUSER);
 		} else {
 			syslog(LOG_ERR, "bad opt %s", cpopt);
 			return (1);
@@ -2930,7 +2976,7 @@ do_export_mount(struct exportlist *ep, struct statfs *
 		defgrp.gr_type = GT_DEFAULT;
 		defgrp.gr_next = NULL;
 		/* We have an entry for all other hosts/nets. */
-		LOGDEBUG("ex_defexflags=0x%x", ep->ex_defexflags);
+		LOGDEBUG("ex_defexflags=0x%jx", (uintmax_t)ep->ex_defexflags);
 		ret = do_mount(ep, &defgrp, ep->ex_defexflags, &ep->ex_defanon,
 		    ep->ex_fsdir, dirlen, fsp, ep->ex_defnumsecflavors,
 		    ep->ex_defsecflavors);
@@ -2941,8 +2987,8 @@ do_export_mount(struct exportlist *ep, struct statfs *
 	/* Do a mount for each group. */
 	grp = ep->ex_grphead;
 	while (grp != NULL) {
-		LOGDEBUG("do mount gr_type=0x%x gr_exflags=0x%x",
-		    grp->gr_type, grp->gr_exflags);
+		LOGDEBUG("do mount gr_type=0x%x gr_exflags=0x%jx",
+		    grp->gr_type, (uintmax_t)grp->gr_exflags);
 		ret = do_mount(ep, grp, grp->gr_exflags, &grp->gr_anon,
 		    ep->ex_fsdir, dirlen, fsp, grp->gr_numsecflavors,
 		    grp->gr_secflavors);
@@ -2958,8 +3004,8 @@ do_export_mount(struct exportlist *ep, struct statfs *
  * the kernel.
  */
 static int
-do_mount(struct exportlist *ep, struct grouplist *grp, int exflags,
-    struct xucred *anoncrp, char *dirp, int dirplen, struct statfs *fsb,
+do_mount(struct exportlist *ep, struct grouplist *grp, uint64_t exflags,
+    struct expcred *anoncrp, char *dirp, int dirplen, struct statfs *fsb,
     int numsecflavors, int *secflavors)
 {
 	struct statfs fsb1;
@@ -2985,8 +3031,14 @@ do_mount(struct exportlist *ep, struct grouplist *grp,
 	bzero(eap, sizeof (struct export_args));
 	bzero(errmsg, sizeof(errmsg));
 	eap->ex_flags = exflags;
-	eap->ex_anon = *anoncrp;
-	LOGDEBUG("do_mount exflags=0x%x", exflags);
+	eap->ex_uid = anoncrp->cr_uid;
+	eap->ex_ngroups = anoncrp->cr_ngroups;
+	if (eap->ex_ngroups > 0) {
+		eap->ex_groups = malloc(eap->ex_ngroups * sizeof(gid_t));
+		memcpy(eap->ex_groups, anoncrp->cr_groups, eap->ex_ngroups *
+		    sizeof(gid_t));
+	}
+	LOGDEBUG("do_mount exflags=0x%jx", (uintmax_t)exflags);
 	eap->ex_indexfile = ep->ex_indexfile;
 	if (grp->gr_type == GT_HOST)
 		ai = grp->gr_ptr.gt_addrinfo;
@@ -3056,9 +3108,11 @@ do_mount(struct exportlist *ep, struct grouplist *grp,
 		 */
 		if (v4root_phase == 2) {
 			nfsea.fspec = v4root_dirpath;
-			if (nfssvc(NFSSVC_V4ROOTEXPORT, (caddr_t)&nfsea) < 0) {
+			if (nfssvc(NFSSVC_V4ROOTEXPORT | NFSSVC_NEWSTRUCT,
+			    (caddr_t)&nfsea) < 0) {
 				syslog(LOG_ERR, "Exporting V4: failed");
-				return (2);
+				ret = 2;
+				goto error_exit;
 			}
 		} else {
 			/*
@@ -3109,9 +3163,9 @@ do_mount(struct exportlist *ep, struct grouplist *grp,
 					goto error_exit;
 				}
 				/* back up over the last component */
-				while (*cp == '/' && cp > dirp)
+				while (cp > dirp && *cp == '/')
 					cp--;
-				while (*(cp - 1) != '/' && cp > dirp)
+				while (cp > dirp && *(cp - 1) != '/')
 					cp--;
 				if (cp == dirp) {
 					if (debug)
@@ -3128,8 +3182,7 @@ do_mount(struct exportlist *ep, struct grouplist *grp,
 				 * filesystem.
 				 */
 				if (statfs(dirp, &fsb1) != 0 ||
-				    bcmp(&fsb1.f_fsid, &fsb->f_fsid,
-				    sizeof (fsb1.f_fsid)) != 0) {
+				    fsidcmp(&fsb1.f_fsid, &fsb->f_fsid) != 0) {
 					*cp = savedc;
 					syslog(LOG_ERR,
 					    "can't export %s %s", dirp,
@@ -3145,7 +3198,7 @@ do_mount(struct exportlist *ep, struct grouplist *grp,
 		 * If this is the public directory, get the file handle
 		 * and load it into the kernel via the nfssvc() syscall.
 		 */
-		if ((exflags & MNTEX_PUBLIC) != 0) {
+		if ((exflags & MNT_EXPUBLIC) != 0) {
 			fhandle_t fh;
 			char *public_name;
 
@@ -3174,6 +3227,7 @@ skip:
 	if (cp)
 		*cp = savedc;
 error_exit:
+	free(eap->ex_groups);
 	/* free strings allocated by strdup() in getmntopts.c */
 	if (iov != NULL) {
 		free(iov[0].iov_base); /* fstype */
@@ -3400,22 +3454,19 @@ get_line(void)
  * Parse a description of a credential.
  */
 static void
-parsecred(char *namelist, struct xucred *cr)
+parsecred(char *namelist, struct expcred *cr)
 {
 	char *name;
 	int cnt;
 	char *names;
 	struct passwd *pw;
 	struct group *gr;
-	gid_t groups[XU_NGROUPS + 1];
-	int ngroups;
 
-	cr->cr_version = XUCRED_VERSION;
 	/*
 	 * Set up the unprivileged user.
 	 */
-	cr->cr_uid = 65534;
-	cr->cr_groups[0] = 65533;
+	cr->cr_uid = UID_NOBODY;
+	cr->cr_groups[0] = GID_NOGROUP;
 	cr->cr_ngroups = 1;
 	/*
 	 * Get the user's password table entry.
@@ -3436,19 +3487,24 @@ parsecred(char *namelist, struct xucred *cr)
 			return;
 		}
 		cr->cr_uid = pw->pw_uid;
-		ngroups = XU_NGROUPS + 1;
-		if (getgrouplist(pw->pw_name, pw->pw_gid, groups, &ngroups)) {
+		cr->cr_ngroups = NGROUPS_MAX + 1;
+		if (getgrouplist(pw->pw_name, pw->pw_gid, cr->cr_groups,
+		    &cr->cr_ngroups)) {
 			syslog(LOG_ERR, "too many groups");
-			ngroups = XU_NGROUPS + 1;
+			cr->cr_ngroups = NGROUPS_MAX + 1;
 		}
 
 		/*
 		 * Compress out duplicate.
 		 */
-		cr->cr_ngroups = ngroups - 1;
-		cr->cr_groups[0] = groups[0];
-		for (cnt = 2; cnt < ngroups; cnt++)
-			cr->cr_groups[cnt - 1] = groups[cnt];
+		if (cr->cr_ngroups > 1 && cr->cr_groups[0] ==
+		    cr->cr_groups[1]) {
+			for (cnt = 2; cnt < cr->cr_ngroups; cnt++)
+				cr->cr_groups[cnt - 1] = cr->cr_groups[cnt];
+			cr->cr_ngroups--;
+		}
+		if (cr->cr_ngroups > NGROUPS_MAX)
+			cr->cr_ngroups = NGROUPS_MAX;
 		return;
 	}
 	/*
@@ -3464,7 +3520,7 @@ parsecred(char *namelist, struct xucred *cr)
 		return;
 	}
 	cr->cr_ngroups = 0;
-	while (names != NULL && *names != '\0' && cr->cr_ngroups < XU_NGROUPS) {
+	while (names != NULL && *names != '\0' && cr->cr_ngroups < NGROUPS_MAX) {
 		name = strsep_quote(&names, ":");
 		if (isdigit(*name) || *name == '-') {
 			cr->cr_groups[cr->cr_ngroups++] = atoi(name);
@@ -3476,7 +3532,7 @@ parsecred(char *namelist, struct xucred *cr)
 			cr->cr_groups[cr->cr_ngroups++] = gr->gr_gid;
 		}
 	}
-	if (names != NULL && *names != '\0' && cr->cr_ngroups == XU_NGROUPS)
+	if (names != NULL && *names != '\0' && cr->cr_ngroups == NGROUPS_MAX)
 		syslog(LOG_ERR, "too many groups");
 }
 
@@ -3796,4 +3852,14 @@ terminate(int sig __unused)
 	rpcb_unset(MOUNTPROG, MOUNTVERS, NULL);
 	rpcb_unset(MOUNTPROG, MOUNTVERS3, NULL);
 	exit (0);
+}
+
+static void
+cp_cred(struct expcred *outcr, struct expcred *incr)
+{
+
+	outcr->cr_uid = incr->cr_uid;
+	outcr->cr_ngroups = incr->cr_ngroups;
+	memcpy(outcr->cr_groups, incr->cr_groups, incr->cr_ngroups *
+	    sizeof(gid_t));
 }



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202008222256.07MMuoZZ007827>