From owner-svn-src-all@freebsd.org Sat Oct 10 00:01:41 2020 Return-Path: Delivered-To: svn-src-all@mailman.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.nyi.freebsd.org (Postfix) with ESMTP id 2E84A430E2D; Sat, 10 Oct 2020 00:01:41 +0000 (UTC) (envelope-from rmacklem@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4C7Q8j0TlBz3Zsr; Sat, 10 Oct 2020 00:01:41 +0000 (UTC) (envelope-from rmacklem@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id E8F87217FD; Sat, 10 Oct 2020 00:01:40 +0000 (UTC) (envelope-from rmacklem@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id 09A01eLj072591; Sat, 10 Oct 2020 00:01:40 GMT (envelope-from rmacklem@FreeBSD.org) Received: (from rmacklem@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id 09A01ew2072529; Sat, 10 Oct 2020 00:01:40 GMT (envelope-from rmacklem@FreeBSD.org) Message-Id: <202010100001.09A01ew2072529@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: rmacklem set sender to rmacklem@FreeBSD.org using -f From: Rick Macklem Date: Sat, 10 Oct 2020 00:01:40 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r366595 - head/usr.sbin/mountd X-SVN-Group: head X-SVN-Commit-Author: rmacklem X-SVN-Commit-Paths: head/usr.sbin/mountd X-SVN-Commit-Revision: 366595 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.33 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 10 Oct 2020 00:01:41 -0000 Author: rmacklem Date: Sat Oct 10 00:01:40 2020 New Revision: 366595 URL: https://svnweb.freebsd.org/changeset/base/366595 Log: Modify mountd.c so that it does not always malloc 4K for the map credentials. r362163 upgraded mountd so that it could handle MAX_NGROUPS groups for the anonymous user credentials (the ones provided by -maproot and -mapall exports options). The problem is that this resulted in every export structure growing by about 4Kbytes, because the cr_groups field went from 16->MAX_NGROUPS. This patch fixes this by only including a small 32 element cr_groups in the structure and then malloc()'ng cr_groups when a larger one is needed. The value of SMALLNGROUPS is arbitrarily set to 32, assuming most users used by -maproot or -mapall will be in <= 32 groups. Reviewed by: kib, freqlabs Differential Revision: https://reviews.freebsd.org/D26521 Modified: head/usr.sbin/mountd/mountd.c Modified: head/usr.sbin/mountd/mountd.c ============================================================================== --- head/usr.sbin/mountd/mountd.c Fri Oct 9 23:49:42 2020 (r366594) +++ head/usr.sbin/mountd/mountd.c Sat Oct 10 00:01:40 2020 (r366595) @@ -115,11 +115,15 @@ struct dirlist { /* * maproot/mapall credentials. + * cr_smallgrps can be used for a group list up to SMALLNGROUPS in size. + * Larger group lists are malloc'd/free'd. */ +#define SMALLNGROUPS 32 struct expcred { uid_t cr_uid; int cr_ngroups; - gid_t cr_groups[NGROUPS_MAX + 1]; + gid_t cr_smallgrps[SMALLNGROUPS]; + gid_t *cr_groups; }; struct exportlist { @@ -1514,6 +1518,7 @@ get_exportlist_one(int passno) uint64_t exflags; v4root_phase = 0; + anon.cr_groups = NULL; dirhead = (struct dirlist *)NULL; while (get_line()) { if (debug) @@ -1527,6 +1532,7 @@ get_exportlist_one(int passno) * Set defaults. */ has_host = FALSE; + anon.cr_groups = anon.cr_smallgrps; anon.cr_uid = UID_NOBODY; anon.cr_ngroups = 1; anon.cr_groups[0] = GID_NOGROUP; @@ -1822,6 +1828,10 @@ nextline: free_dir(dirhead); dirhead = (struct dirlist *)NULL; } + if (anon.cr_groups != anon.cr_smallgrps) { + free(anon.cr_groups); + anon.cr_groups = NULL; + } } } @@ -2905,6 +2915,8 @@ free_exp(struct exportlist *ep) grp = grp->gr_next; free_grp(tgrp); } + if (ep->ex_defanon.cr_groups != ep->ex_defanon.cr_smallgrps) + free(ep->ex_defanon.cr_groups); free((caddr_t)ep); } @@ -3457,14 +3469,17 @@ static void parsecred(char *namelist, struct expcred *cr) { char *name; - int cnt; + int inpos; char *names; struct passwd *pw; struct group *gr; + gid_t groups[NGROUPS_MAX + 1]; + int ngroups; /* * Set up the unprivileged user. */ + cr->cr_groups = cr->cr_smallgrps; cr->cr_uid = UID_NOBODY; cr->cr_groups[0] = GID_NOGROUP; cr->cr_ngroups = 1; @@ -3487,24 +3502,28 @@ parsecred(char *namelist, struct expcred *cr) return; } cr->cr_uid = pw->pw_uid; - cr->cr_ngroups = NGROUPS_MAX + 1; - if (getgrouplist(pw->pw_name, pw->pw_gid, cr->cr_groups, - &cr->cr_ngroups)) { + ngroups = NGROUPS_MAX + 1; + if (getgrouplist(pw->pw_name, pw->pw_gid, groups, &ngroups)) { syslog(LOG_ERR, "too many groups"); - cr->cr_ngroups = NGROUPS_MAX + 1; + ngroups = NGROUPS_MAX + 1; } /* * Compress out duplicate. */ - 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; + if (ngroups > 1 && groups[0] == groups[1]) { + ngroups--; + inpos = 2; + } else + inpos = 1; + if (ngroups > NGROUPS_MAX) + ngroups = NGROUPS_MAX; + if (ngroups > SMALLNGROUPS) + cr->cr_groups = malloc(ngroups * sizeof(gid_t)); + cr->cr_ngroups = ngroups; + cr->cr_groups[0] = groups[0]; + memcpy(&cr->cr_groups[1], &groups[inpos], (ngroups - 1) * + sizeof(gid_t)); return; } /* @@ -3523,17 +3542,20 @@ parsecred(char *namelist, struct expcred *cr) 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); + groups[cr->cr_ngroups++] = atoi(name); } else { if ((gr = getgrnam(name)) == NULL) { syslog(LOG_ERR, "unknown group: %s", name); continue; } - cr->cr_groups[cr->cr_ngroups++] = gr->gr_gid; + groups[cr->cr_ngroups++] = gr->gr_gid; } } if (names != NULL && *names != '\0' && cr->cr_ngroups == NGROUPS_MAX) syslog(LOG_ERR, "too many groups"); + if (cr->cr_ngroups > SMALLNGROUPS) + cr->cr_groups = malloc(cr->cr_ngroups * sizeof(gid_t)); + memcpy(cr->cr_groups, groups, cr->cr_ngroups * sizeof(gid_t)); } #define STRSIZ (MNTNAMLEN+MNTPATHLEN+50) @@ -3642,6 +3664,8 @@ free_grp(struct grouplist *grp) if (grp->gr_ptr.gt_net.nt_name) free(grp->gr_ptr.gt_net.nt_name); } + if (grp->gr_anon.cr_groups != grp->gr_anon.cr_smallgrps) + free(grp->gr_anon.cr_groups); free((caddr_t)grp); } @@ -3860,6 +3884,10 @@ cp_cred(struct expcred *outcr, struct expcred *incr) outcr->cr_uid = incr->cr_uid; outcr->cr_ngroups = incr->cr_ngroups; + if (outcr->cr_ngroups > SMALLNGROUPS) + outcr->cr_groups = malloc(outcr->cr_ngroups * sizeof(gid_t)); + else + outcr->cr_groups = outcr->cr_smallgrps; memcpy(outcr->cr_groups, incr->cr_groups, incr->cr_ngroups * sizeof(gid_t)); }