The branch main has been updated by kevans:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=f61c48f4403fc8c69f9b933d3f1bd9663008b0eb

commit f61c48f4403fc8c69f9b933d3f1bd9663008b0eb
Author:     Kyle Evans <kev...@freebsd.org>
AuthorDate: 2025-08-01 00:50:48 +0000
Commit:     Kyle Evans <kev...@freebsd.org>
CommitDate: 2025-08-01 00:50:48 +0000

    kern: rename crsetgroups_fallback, document it in ucred(9)
    
    As of FreeBSD 15.0, crsetgroups() *only* sets supplementary groups,
    while crsetgroups_and_egid() will do both using an array of the same
    style that previous versions used for crsetgroups() -- i.e., the first
    element is the egid, and the remainder are supplementary groups.
    
    Unlike the previous iteration of crsetgroups(), crsetgroups_and_egid()
    is less prone to misuse as the caller must provide a default egid to use
    in case the array is empty.  This is particularly useful for groups
    being set from data provided by userland.
    
    Reviewed by:    olce
    Suggested by:   olce
    Differential Revision:  https://reviews.freebsd.org/D51647
---
 share/man/man9/ucred.9              | 19 +++++++++++++++++--
 sys/fs/nfs/nfs_commonport.c         |  2 +-
 sys/fs/nfs/nfs_commonsubs.c         |  2 +-
 sys/fs/nfsserver/nfs_nfsdport.c     |  2 +-
 sys/fs/nfsserver/nfs_nfsdsocket.c   |  2 +-
 sys/kern/kern_prot.c                | 10 +++++-----
 sys/kern/vfs_export.c               |  4 ++--
 sys/rpc/rpcsec_gss/svc_rpcsec_gss.c |  2 +-
 sys/rpc/svc_auth.c                  |  4 ++--
 sys/sys/ucred.h                     |  4 ++--
 10 files changed, 33 insertions(+), 18 deletions(-)

diff --git a/share/man/man9/ucred.9 b/share/man/man9/ucred.9
index 16de37dd8b35..38759bddb5b0 100644
--- a/share/man/man9/ucred.9
+++ b/share/man/man9/ucred.9
@@ -54,6 +54,9 @@
 .Ft void
 .Fn crsetgroups "struct ucred *cr" "int ngrp" "gid_t *groups"
 .Ft void
+.Fn crsetgroups_and_egid "struct ucred *cr" "int ngrp" "gid_t *groups" \
+    "gid_t default_egid"
+.Ft void
 .Fn cru2x "struct ucred *cr" "struct xucred *xcr"
 .Sh DESCRIPTION
 The
@@ -110,16 +113,28 @@ The actual copying is performed by
 .Pp
 The
 .Fn crsetgroups
-function sets the
+and
+.Fn crsetgroups_and_egid
+functions set the
 .Va cr_groups
 and
 .Va cr_ngroups
 variables and allocates space as needed.
-It also truncates the group list to the current maximum number of
+They also truncate the group list to the current maximum number of
 groups.
 No other mechanism should be used to modify the
 .Va cr_groups
 array.
+Note that
+.Fn crsetgroups_and_egid
+will interpret the first element of
+.Va groups
+as the new effective GID and the rest of the array as the supplementary groups,
+and
+.Va default_egid
+will be used as the new effective GID only if
+.Va groups
+is empty.
 .Pp
 The
 .Fn cru2x
diff --git a/sys/fs/nfs/nfs_commonport.c b/sys/fs/nfs/nfs_commonport.c
index e382b22fed74..e5fdb395c9f7 100644
--- a/sys/fs/nfs/nfs_commonport.c
+++ b/sys/fs/nfs/nfs_commonport.c
@@ -258,7 +258,7 @@ newnfs_copycred(struct nfscred *nfscr, struct ucred *cr)
        KASSERT(nfscr->nfsc_ngroups >= 0,
            ("newnfs_copycred: negative nfsc_ngroups"));
        cr->cr_uid = nfscr->nfsc_uid;
-       crsetgroups_fallback(cr, nfscr->nfsc_ngroups, nfscr->nfsc_groups,
+       crsetgroups_and_egid(cr, nfscr->nfsc_ngroups, nfscr->nfsc_groups,
            GID_NOGROUP);
 }
 
diff --git a/sys/fs/nfs/nfs_commonsubs.c b/sys/fs/nfs/nfs_commonsubs.c
index a957315aaa12..4ffc4ce5c29f 100644
--- a/sys/fs/nfs/nfs_commonsubs.c
+++ b/sys/fs/nfs/nfs_commonsubs.c
@@ -4143,7 +4143,7 @@ nfssvc_idname(struct nfsd_idargs *nidp)
                         */
                        cr = crget();
                        cr->cr_uid = cr->cr_ruid = cr->cr_svuid = nidp->nid_uid;
-                       crsetgroups_fallback(cr, nidp->nid_ngroup, grps,
+                       crsetgroups_and_egid(cr, nidp->nid_ngroup, grps,
                            GID_NOGROUP);
                        cr->cr_rgid = cr->cr_svgid = cr->cr_gid;
                        cr->cr_prison = curthread->td_ucred->cr_prison;
diff --git a/sys/fs/nfsserver/nfs_nfsdport.c b/sys/fs/nfsserver/nfs_nfsdport.c
index 9e1a198bf34a..8c427c66c156 100644
--- a/sys/fs/nfsserver/nfs_nfsdport.c
+++ b/sys/fs/nfsserver/nfs_nfsdport.c
@@ -3466,7 +3466,7 @@ nfsd_excred(struct nfsrv_descript *nd, struct nfsexstuff 
*exp,
                        nd->nd_cred->cr_gid = credanon->cr_gid;
                        /*
                         * 'credanon' is already a 'struct ucred' that was built
-                        * internally with calls to crsetgroups_fallback(), so
+                        * internally with calls to crsetgroups_and_egid(), so
                         * we don't need a fallback here.
                         */
                        crsetgroups(nd->nd_cred, credanon->cr_ngroups,
diff --git a/sys/fs/nfsserver/nfs_nfsdsocket.c 
b/sys/fs/nfsserver/nfs_nfsdsocket.c
index d1b6198ba0e1..d6832b4f74be 100644
--- a/sys/fs/nfsserver/nfs_nfsdsocket.c
+++ b/sys/fs/nfsserver/nfs_nfsdsocket.c
@@ -1425,7 +1425,7 @@ nfsrv_createrootcred(void)
 
        cr = crget();
        cr->cr_uid = cr->cr_ruid = cr->cr_svuid = UID_ROOT;
-       crsetgroups_fallback(cr, 0, NULL, GID_WHEEL);
+       crsetgroups_and_egid(cr, 0, NULL, GID_WHEEL);
        cr->cr_rgid = cr->cr_svgid = cr->cr_gid;
        cr->cr_prison = curthread->td_ucred->cr_prison;
        prison_hold(cr->cr_prison);
diff --git a/sys/kern/kern_prot.c b/sys/kern/kern_prot.c
index 632be229af5b..6bdef84a34c1 100644
--- a/sys/kern/kern_prot.c
+++ b/sys/kern/kern_prot.c
@@ -2928,19 +2928,19 @@ crsetgroups(struct ucred *cr, int ngrp, const gid_t 
*groups)
 }
 
 /*
- * Same as crsetgroups() but accepts an empty groups array.
+ * Same as crsetgroups() but sets the effective GID as well.
  *
  * This function ensures that an effective GID is always present in 
credentials.
- * An empty array will only set the effective GID to the fallback, while a
+ * An empty array will only set the effective GID to the default_egid, while a
  * non-empty array will peel off groups[0] to set as the effective GID and use
  * the remainder, if any, as supplementary groups.
  */
 void
-crsetgroups_fallback(struct ucred *cr, int ngrp, const gid_t *groups,
-    const gid_t fallback)
+crsetgroups_and_egid(struct ucred *cr, int ngrp, const gid_t *groups,
+    const gid_t default_egid)
 {
        if (ngrp == 0) {
-               cr->cr_gid = fallback;
+               cr->cr_gid = default_egid;
                cr->cr_ngroups = 0;
                cr->cr_flags |= CRED_FLAG_GROUPSET;
                return;
diff --git a/sys/kern/vfs_export.c b/sys/kern/vfs_export.c
index a314bda164de..bd7caa01e153 100644
--- a/sys/kern/vfs_export.c
+++ b/sys/kern/vfs_export.c
@@ -134,7 +134,7 @@ vfs_hang_addrlist(struct mount *mp, struct netexport *nep,
                np->netc_exflags = argp->ex_flags;
                np->netc_anon = crget();
                np->netc_anon->cr_uid = argp->ex_uid;
-               crsetgroups_fallback(np->netc_anon, argp->ex_ngroups,
+               crsetgroups_and_egid(np->netc_anon, argp->ex_ngroups,
                    argp->ex_groups, GID_NOGROUP);
                np->netc_anon->cr_prison = &prison0;
                prison_hold(np->netc_anon->cr_prison);
@@ -213,7 +213,7 @@ vfs_hang_addrlist(struct mount *mp, struct netexport *nep,
        np->netc_exflags = argp->ex_flags;
        np->netc_anon = crget();
        np->netc_anon->cr_uid = argp->ex_uid;
-       crsetgroups_fallback(np->netc_anon, argp->ex_ngroups, argp->ex_groups,
+       crsetgroups_and_egid(np->netc_anon, argp->ex_ngroups, argp->ex_groups,
            GID_NOGROUP);
        np->netc_anon->cr_prison = &prison0;
        prison_hold(np->netc_anon->cr_prison);
diff --git a/sys/rpc/rpcsec_gss/svc_rpcsec_gss.c 
b/sys/rpc/rpcsec_gss/svc_rpcsec_gss.c
index b1790dd167d5..51077c71822c 100644
--- a/sys/rpc/rpcsec_gss/svc_rpcsec_gss.c
+++ b/sys/rpc/rpcsec_gss/svc_rpcsec_gss.c
@@ -537,7 +537,7 @@ rpc_gss_svc_getcred(struct svc_req *req, struct ucred 
**crp, int *flavorp)
        cr = client->cl_cred = crget();
        cr->cr_uid = cr->cr_ruid = cr->cr_svuid = uc->uid;
        cr->cr_rgid = cr->cr_svgid = uc->gid;
-       crsetgroups_fallback(cr, uc->gidlen, uc->gidlist, uc->gid);
+       crsetgroups_and_egid(cr, uc->gidlen, uc->gidlist, uc->gid);
        cr->cr_prison = curthread->td_ucred->cr_prison;
        prison_hold(cr->cr_prison);
        *crp = crhold(cr);
diff --git a/sys/rpc/svc_auth.c b/sys/rpc/svc_auth.c
index 838fa9ed313a..acbb1112e270 100644
--- a/sys/rpc/svc_auth.c
+++ b/sys/rpc/svc_auth.c
@@ -192,7 +192,7 @@ svc_getcred(struct svc_req *rqst, struct ucred **crp, int 
*flavorp)
                        return (FALSE);
                cr = crget();
                cr->cr_uid = cr->cr_ruid = cr->cr_svuid = xprt->xp_uid;
-               crsetgroups_fallback(cr, xprt->xp_ngrps, xprt->xp_gidp, 
GID_NOGROUP);
+               crsetgroups_and_egid(cr, xprt->xp_ngrps, xprt->xp_gidp, 
GID_NOGROUP);
                cr->cr_rgid = cr->cr_svgid = cr->cr_gid;
                cr->cr_prison = curthread->td_ucred->cr_prison;
                prison_hold(cr->cr_prison);
@@ -207,7 +207,7 @@ svc_getcred(struct svc_req *rqst, struct ucred **crp, int 
*flavorp)
                        return (FALSE);
                cr = crget();
                cr->cr_uid = cr->cr_ruid = cr->cr_svuid = xcr->cr_uid;
-               crsetgroups_fallback(cr, xcr->cr_ngroups, xcr->cr_groups, 
GID_NOGROUP);
+               crsetgroups_and_egid(cr, xcr->cr_ngroups, xcr->cr_groups, 
GID_NOGROUP);
                cr->cr_rgid = cr->cr_svgid = cr->cr_gid;
                cr->cr_prison = curthread->td_ucred->cr_prison;
                prison_hold(cr->cr_prison);
diff --git a/sys/sys/ucred.h b/sys/sys/ucred.h
index cd4efcb71c0d..9c1d8545af34 100644
--- a/sys/sys/ucred.h
+++ b/sys/sys/ucred.h
@@ -242,8 +242,8 @@ void        crcowfree(struct thread *td);
 void   cru2x(struct ucred *cr, struct xucred *xcr);
 void   cru2xt(struct thread *td, struct xucred *xcr);
 void   crsetgroups(struct ucred *cr, int ngrp, const gid_t *groups);
-void   crsetgroups_fallback(struct ucred *cr, int ngrp, const gid_t *groups,
-           const gid_t fallback);
+void   crsetgroups_and_egid(struct ucred *cr, int ngrp, const gid_t *groups,
+           const gid_t default_egid);
 bool   cr_xids_subset(struct ucred *active_cred, struct ucred *obj_cred);
 
 /*

Reply via email to