git: fb651b231863 - stable/14 - mountd(8): parsecred(): Fallback to "nogroup" or GID_NOGROUP
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Thu, 16 Jan 2025 18:08:21 UTC
The branch stable/14 has been updated by olce:
URL: https://cgit.FreeBSD.org/src/commit/?id=fb651b2318631eeceb08dc8ef88e868887ce362e
commit fb651b2318631eeceb08dc8ef88e868887ce362e
Author: Olivier Certner <olce@FreeBSD.org>
AuthorDate: 2024-10-08 09:21:17 +0000
Commit: Olivier Certner <olce@FreeBSD.org>
CommitDate: 2025-01-16 18:06:57 +0000
mountd(8): parsecred(): Fallback to "nogroup" or GID_NOGROUP
In the 'uid:gid:gid:...' case (for '-maproot' or '-mapall'), if no GID
is specified at all (i.e., input is of the form 'uid:', with the colon
at the end), mountd(8) would pass credentials with an empty array of
groups to the kernel.
For security reasons, we have put in place a kernel fallback a while
ago, which is to use the single group GID_NOGROUP (see commits
cfbe7a62dc62 ("nfs, rpc: Ensure kernel credentials have at least one
group") and 5169d4307eb9 ("nfs: Fallback to GID_NOGROUP on no groups")).
Here, as we are in userland, we first try to find the GID number
corresponding to "nogroup", and only then fall back to GID_NOGROUP, as
nfsuserd(8) does.
Approved by: markj (mentor)
MFC after: 2 weeks
Sponsored by: The FreeBSD Foundation
Differential Revision: https://reviews.freebsd.org/D47011
(cherry picked from commit bdc259ef382f76b1821d4356049d5b856c42901a)
---
usr.sbin/mountd/mountd.c | 27 +++++++++++++++++++++++++--
1 file changed, 25 insertions(+), 2 deletions(-)
diff --git a/usr.sbin/mountd/mountd.c b/usr.sbin/mountd/mountd.c
index f7ab5d6d696d..8ee8280b5d67 100644
--- a/usr.sbin/mountd/mountd.c
+++ b/usr.sbin/mountd/mountd.c
@@ -277,6 +277,8 @@ static int xdr_mlist(XDR *, caddr_t);
static void terminate(int);
static void cp_cred(struct expcred *, struct expcred *);
+static gid_t nogroup();
+
#define EXPHASH(f) (fnv_32_buf((f), sizeof(fsid_t), 0) % exphashsize)
static struct exportlisthead *exphead = NULL;
static struct exportlisthead *oldexphead = NULL;
@@ -1589,7 +1591,7 @@ get_exportlist_one(int passno)
anon.cr_groups = anon.cr_smallgrps;
anon.cr_uid = UID_NOBODY;
anon.cr_ngroups = 1;
- anon.cr_groups[0] = GID_NOGROUP;
+ anon.cr_groups[0] = nogroup();
exflags = MNT_EXPORTED;
got_nondir = 0;
opt_flags = 0;
@@ -3625,7 +3627,7 @@ parsecred(char *namelist, struct expcred *cr)
*/
cr->cr_groups = cr->cr_smallgrps;
cr->cr_uid = UID_NOBODY;
- cr->cr_groups[0] = GID_NOGROUP;
+ cr->cr_groups[0] = nogroup();
cr->cr_ngroups = 1;
/*
* Get the user's password table entry.
@@ -3694,6 +3696,11 @@ parsecred(char *namelist, struct expcred *cr)
}
groups[cr->cr_ngroups++] = group;
}
+ if (cr->cr_ngroups == 0) {
+ /* cr->cr_groups[0] filled at start with nogroup(). */
+ cr->cr_ngroups = 1;
+ return;
+ }
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));
@@ -4079,3 +4086,19 @@ cp_cred(struct expcred *outcr, struct expcred *incr)
memcpy(outcr->cr_groups, incr->cr_groups, incr->cr_ngroups *
sizeof(gid_t));
}
+
+static gid_t
+nogroup()
+{
+ static gid_t nogroup = 0; /* 0 means unset. */
+
+ if (nogroup == 0) {
+ const struct group *gr = getgrnam("nogroup");
+
+ if (gr != NULL && gr->gr_gid != 0)
+ nogroup = gr->gr_gid;
+ else
+ nogroup = GID_NOGROUP;
+ }
+ return (nogroup);
+}