From nobody Thu Jan 16 18:08:28 2025 X-Original-To: dev-commits-src-all@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4YYrT93VNZz5kl3B; Thu, 16 Jan 2025 18:08:29 +0000 (UTC) (envelope-from git@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 "R11" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4YYrT85h9mz3Rpm; Thu, 16 Jan 2025 18:08:28 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1737050908; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=jcOyTTeb6kYAp6S1fpWCz9WVxwjKvLIm2ZMmbi4aqhA=; b=gJWoo40nDPEtNcC4g8ZYXo5Lnlrg1mY5JxIidOwBEtqxn2wJJn2gzxJQtmKbh0i4cUfVt7 7i9DJCtM8zfovNY6NdbqMRwJp6rZAuKc/Ii0L4SQiykPyITSLeVj+3GekZUPkwe6FCTbqZ WHyw7xbUfopoxDqGSyS2gVn16+e4uzFIwqwDu6SXGqtNWQ/9BqevCkJZTzjAYg/6jCudK5 QzLS+iTPg6wxEvM3tKa6/NFU60RvDxCV5rJiOsarHzwkoUzf845AxAyqn8AvGmAaWG3+gS Axtgvpbwn06yNeNt7X5EfxuAgq99NHAvS0MBohKxZgtssCw1XOX82pnsMVjvBg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1737050908; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=jcOyTTeb6kYAp6S1fpWCz9WVxwjKvLIm2ZMmbi4aqhA=; b=NQYVG7gz+D0VNDJJ85EgYaS6CNt5Pse5cI9Z8CWOZlDNddw+x6da9EKYL7Q+Pkz/9G6pZN EmdpYyR7i5kMLHBVYIsE1139FRMsQRZIfRb9BtCqrwy+v591hMX1g3rsgOcLtuJdWAp7dG czRsS6Rc0w0KgRoDbkIRYuhF9PVlOIuoAvcYiTAOS3f+UT4tGvoTFZd5rUAJ0XcgYtMYg9 bn4sjHtUY+E8fg4F9yaFO9k7POdd/I9K0Kla0v+HSh2/lMHtOz/yhfL8nNrTdBeGynbo5i 0SlYaMNuxz5iDbkAXMlEKQCR14KXjnUz3o5cnH3DujVH6F92IYMip6C5Ih0kTQ== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1737050908; a=rsa-sha256; cv=none; b=Ws2APXKCgdYWLdIFsbBhMMG309tHtpjC/0CR42WaKd7raAZmTEWhcbgHzpRRHy9MJZZ3Xr p6H6086AJ3ErgikNCpioKAq+amv5KWD4bYTdGz7HiqClwCt9dDes8ckVA4b8dNdUeLU3C0 jPC+ShvxlH3drCor9NJT/tlkWbOAACpaNyNHTJG5csJ5uQtywWxWzS+bZf987bXTFTqCC+ hAIrZwv5/X9zhbxWkO/CwYrdcvHHPgvlOlJUMVYXo+VdPdpWo6G0YrGNgr9PLzg/OZdqSx a1OejcJkITF+gUhE69mpnkzVpYCAKIX7CWH1JSbz2eRtlAaOZW9I7YhfIBufOw== ARC-Authentication-Results: i=1; mx1.freebsd.org; none Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (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 did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 4YYrT85DgdzkKk; Thu, 16 Jan 2025 18:08:28 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.18.1/8.18.1) with ESMTP id 50GI8SPK092440; Thu, 16 Jan 2025 18:08:28 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.18.1/8.18.1/Submit) id 50GI8SqF092437; Thu, 16 Jan 2025 18:08:28 GMT (envelope-from git) Date: Thu, 16 Jan 2025 18:08:28 GMT Message-Id: <202501161808.50GI8SqF092437@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org From: Olivier Certner Subject: git: ca9614d8f64a - stable/14 - mountd(8): Allow to pass {NGROUPS_MAX} + 1 groups List-Id: Commit messages for all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-all@freebsd.org Sender: owner-dev-commits-src-all@FreeBSD.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: olce X-Git-Repository: src X-Git-Refname: refs/heads/stable/14 X-Git-Reftype: branch X-Git-Commit: ca9614d8f64a7de19ba1f1cd9d6927047dd3d032 Auto-Submitted: auto-generated The branch stable/14 has been updated by olce: URL: https://cgit.FreeBSD.org/src/commit/?id=ca9614d8f64a7de19ba1f1cd9d6927047dd3d032 commit ca9614d8f64a7de19ba1f1cd9d6927047dd3d032 Author: Olivier Certner AuthorDate: 2024-10-08 12:30:03 +0000 Commit: Olivier Certner CommitDate: 2025-01-16 18:06:59 +0000 mountd(8): Allow to pass {NGROUPS_MAX} + 1 groups NGROUPS_MAX is just the minimum maximum of the number of allowed supplementary groups. The actual runtime value may be greater. Allow more groups to be specified accordingly (now that, a few commits ago, nmount(2) has been changed similarly). To this end, we just allocate once and for all a static array called 'tmp_groups' big enough to hold {NGROUPS_MAX} + 1 groups (the maximum number of supplementary groups plus the effective GID, which we store in a variable named 'tngroups_max' to avoid confusion with the kernel variable 'ngroups_max' holding only the maximum number of *supplementary* groups) in main() and use this temporary space in get_exportlist_one(), do_opt() and parsecred(). Doing so in passing fixes a (benign) memory leak in case "-maproot" and/or "-mapall" were specified multiple times and the first option comprised more than SMALLNGROUPS. parsecred() does not use 'cr_smallgrps' anymore, but we have kept 'cr_smallgrps'/SMALLNGROUPS as 'struct expcred' is also included in 'struct exportlist' and 'struct grouplist', and thus this preallocated field still results in an optimization for the common case of small number of groups (although its real impact is probably negligible and arguably was not worth the trouble). While here, in do_mount(), remove some unnecessary groups array allocation and copying. Reviewed by: rmacklem (older version) Approved by: markj (mentor) MFC after: 2 weeks Relnotes: yes Sponsored by: The FreeBSD Foundation Differential Revision: https://reviews.freebsd.org/D47016 (cherry picked from commit e87848a8150ed75da29d99a7d0c0bba6cc5129b8) --- usr.sbin/mountd/mountd.c | 70 +++++++++++++++++++++++++----------------------- 1 file changed, 37 insertions(+), 33 deletions(-) diff --git a/usr.sbin/mountd/mountd.c b/usr.sbin/mountd/mountd.c index 5c8c6aad63ec..20055d885b08 100644 --- a/usr.sbin/mountd/mountd.c +++ b/usr.sbin/mountd/mountd.c @@ -70,6 +70,7 @@ static char sccsid[] = "@(#)mountd.c 8.15 (Berkeley) 5/1/95"; #include +#include #include #include #include @@ -258,7 +259,7 @@ 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 out_of_mem(void) __dead2; static void parsecred(char *, struct expcred *); static int parsesec(char *, struct exportlist *); static int put_exlist(struct dirlist *, XDR *, struct dirlist *, @@ -313,6 +314,11 @@ static int has_publicfh = 0; static int has_set_publicfh = 0; static struct pidfh *pfh = NULL; + +/* Temporary storage for credentials' groups. */ +static long tngroups_max; +static gid_t *tmp_groups = NULL; + /* Bits for opt_flags above */ #define OP_MAPROOT 0x01 #define OP_MAPALL 0x02 @@ -445,6 +451,18 @@ main(int argc, char **argv) warn("cannot open or create pidfile"); } + openlog("mountd", LOG_PID, LOG_DAEMON); + + /* How many groups do we support? */ + tngroups_max = sysconf(_SC_NGROUPS_MAX); + if (tngroups_max == -1) + tngroups_max = NGROUPS_MAX; + /* Add space for the effective GID. */ + ++tngroups_max; + tmp_groups = malloc(tngroups_max); + if (tmp_groups == NULL) + out_of_mem(); + s = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP); if (s < 0) have_v6 = 0; @@ -541,7 +559,6 @@ main(int argc, char **argv) exnames = argv; else exnames = exnames_default; - openlog("mountd", LOG_PID, LOG_DAEMON); if (debug) warnx("getting export list"); get_exportlist(0); @@ -1573,9 +1590,9 @@ get_exportlist_one(int passno) int unvis_len; v4root_phase = 0; - anon.cr_groups = NULL; dirhead = (struct dirlist *)NULL; unvis_dir[0] = '\0'; + while (get_line()) { if (debug) warnx("got line %s", line); @@ -1588,9 +1605,9 @@ 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 = tmp_groups; anon.cr_groups[0] = nogroup(); exflags = MNT_EXPORTED; got_nondir = 0; @@ -1920,10 +1937,6 @@ nextline: free_dir(dirhead); dirhead = (struct dirlist *)NULL; } - if (anon.cr_groups != anon.cr_smallgrps) { - free(anon.cr_groups); - anon.cr_groups = NULL; - } } } @@ -3189,11 +3202,11 @@ do_mount(struct exportlist *ep, struct grouplist *grp, uint64_t exflags, eap->ex_flags = 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)); - } + /* + * Use the memory pointed to by 'anoncrp', as it outlives 'eap' which is + * local to this function. + */ + eap->ex_groups = anoncrp->cr_groups; LOGDEBUG("do_mount exflags=0x%jx", (uintmax_t)exflags); eap->ex_indexfile = ep->ex_indexfile; if (grp->gr_type == GT_HOST) @@ -3383,7 +3396,6 @@ 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 */ @@ -3611,21 +3623,19 @@ get_line(void) * Parse a description of a credential. */ static void -parsecred(char *namelist, struct expcred *cr) +parsecred(char *names, struct expcred *cr) { char *name; - char *names; struct passwd *pw; - gid_t groups[NGROUPS_MAX + 1]; - int ngroups; unsigned long name_ul; char *end = NULL; + assert(cr->cr_groups == tmp_groups); + /* * Parse the user and if possible get its password table entry. * 'cr_uid' is filled when exiting this block. */ - names = namelist; name = strsep_quote(&names, ":"); name_ul = strtoul(name, &end, 10); if (*end != '\0' || end == name) @@ -3652,17 +3662,13 @@ parsecred(char *namelist, struct expcred *cr) "can't determine groups", name); goto nogroup; } - cr->cr_uid = pw->pw_uid; - ngroups = NGROUPS_MAX + 1; - if (getgrouplist(pw->pw_name, pw->pw_gid, groups, &ngroups)) { + + cr->cr_ngroups = tngroups_max; + if (getgrouplist(pw->pw_name, pw->pw_gid, + cr->cr_groups, &cr->cr_ngroups) != 0) { syslog(LOG_ERR, "too many groups"); - ngroups = NGROUPS_MAX + 1; + cr->cr_ngroups = tngroups_max; } - - if (ngroups > SMALLNGROUPS) - cr->cr_groups = malloc(ngroups * sizeof(gid_t)); - cr->cr_ngroups = ngroups; - memcpy(cr->cr_groups, groups, ngroups * sizeof(gid_t)); return; } @@ -3686,17 +3692,14 @@ parsecred(char *namelist, struct expcred *cr) } else { group = name_ul; } - if (cr->cr_ngroups == NGROUPS_MAX + 1) { + if (cr->cr_ngroups == tngroups_max) { syslog(LOG_ERR, "too many groups"); break; } - groups[cr->cr_ngroups++] = group; + cr->cr_groups[cr->cr_ngroups++] = group; } if (cr->cr_ngroups == 0) goto nogroup; - 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)); return; nogroup: @@ -4065,6 +4068,7 @@ huphandler(int sig __unused) static void terminate(int sig __unused) { + free(tmp_groups); pidfile_remove(pfh); rpcb_unset(MOUNTPROG, MOUNTVERS, NULL); rpcb_unset(MOUNTPROG, MOUNTVERS3, NULL);