svn commit: r362163 - head/usr.sbin/mountd

Rick Macklem rmacklem at FreeBSD.org
Sun Jun 14 00:40:01 UTC 2020


Author: rmacklem
Date: Sun Jun 14 00:40:00 2020
New Revision: 362163
URL: https://svnweb.freebsd.org/changeset/base/362163

Log:
  Modify mountd to use the new struct export_args committed by r362158.
  
  r362158 modified struct export_args for make the ex_flags field 64bits
  and also changed the anonymous credentials to allow more than 16 groups.
  This patch fixes mountd.c to use the new structure.
  It does allocate larger exportlist and grouplist structures now.
  That will be fixed in a future commit.
  The only visible change will be that the credentials provided for the
  -maproot and -mapall exports options can now have more than 16 groups.
  
  Reviewed by:	kib, freqlabs
  Relnotes:	yes
  Differential Revision:	https://reviews.freebsd.org/D25088

Modified:
  head/usr.sbin/mountd/mountd.c

Modified: head/usr.sbin/mountd/mountd.c
==============================================================================
--- head/usr.sbin/mountd/mountd.c	Sun Jun 14 00:23:06 2020	(r362162)
+++ head/usr.sbin/mountd/mountd.c	Sun Jun 14 00:40:00 2020	(r362163)
@@ -112,6 +112,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 +129,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 +161,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];
@@ -194,7 +203,7 @@ struct fhreturn {
 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 *);
@@ -208,10 +217,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 *);
@@ -226,7 +235,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 *);
@@ -237,13 +246,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);
@@ -259,6 +268,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;
@@ -268,13 +278,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;
@@ -1503,9 +1506,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;
@@ -1521,7 +1525,9 @@ get_exportlist_one(int passno)
 		 * Set defaults.
 		 */
 		has_host = FALSE;
-		anon = def_anon;
+		anon.cr_uid = 65534;
+		anon.cr_ngroups = 1;
+		anon.cr_groups[0] = 65533;
 		exflags = MNT_EXPORTED;
 		got_nondir = 0;
 		opt_flags = 0;
@@ -1738,7 +1744,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,
@@ -1878,7 +1884,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:");
 
@@ -2257,10 +2263,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)
@@ -2425,7 +2431,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;
@@ -2443,7 +2449,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();
@@ -2477,7 +2483,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;
@@ -2526,7 +2533,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;
 	}
 }
@@ -2698,7 +2705,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;
@@ -2960,7 +2967,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);
@@ -2971,8 +2978,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);
@@ -2988,8 +2995,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;
@@ -3015,8 +3022,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;
@@ -3086,9 +3099,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 {
 			/*
@@ -3203,6 +3218,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 */
@@ -3429,17 +3445,14 @@ 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.
 	 */
@@ -3465,27 +3478,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_groups[0] = groups[0];
-		if (ngroups > 1 && groups[0] == groups[1]) {
-			cr->cr_ngroups = ngroups - 1;
-			for (cnt = 2; cnt < ngroups; cnt++)
-				cr->cr_groups[cnt - 1] = groups[cnt];
-		} else {
-			cr->cr_ngroups = ngroups;
-			if (cr->cr_ngroups > XU_NGROUPS)
-				cr->cr_ngroups = XU_NGROUPS;
-			for (cnt = 1; cnt < ngroups; cnt++)
-				cr->cr_groups[cnt] = 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;
 	}
 	/*
@@ -3501,7 +3511,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);
@@ -3513,7 +3523,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");
 }
 
@@ -3833,4 +3843,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));
 }


More information about the svn-src-head mailing list