diff --git a/share/man/man9/ucred.9 b/share/man/man9/ucred.9 --- 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 @@ .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 --- a/sys/fs/nfs/nfs_commonport.c +++ b/sys/fs/nfs/nfs_commonport.c @@ -258,7 +258,7 @@ 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 --- a/sys/fs/nfs/nfs_commonsubs.c +++ b/sys/fs/nfs/nfs_commonsubs.c @@ -4143,7 +4143,7 @@ */ 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 --- a/sys/fs/nfsserver/nfs_nfsdport.c +++ b/sys/fs/nfsserver/nfs_nfsdport.c @@ -3466,7 +3466,7 @@ 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 --- a/sys/fs/nfsserver/nfs_nfsdsocket.c +++ b/sys/fs/nfsserver/nfs_nfsdsocket.c @@ -1425,7 +1425,7 @@ 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 --- a/sys/kern/kern_prot.c +++ b/sys/kern/kern_prot.c @@ -2928,19 +2928,19 @@ } /* - * 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 --- a/sys/kern/vfs_export.c +++ b/sys/kern/vfs_export.c @@ -134,7 +134,7 @@ 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 @@ 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 --- a/sys/rpc/rpcsec_gss/svc_rpcsec_gss.c +++ b/sys/rpc/rpcsec_gss/svc_rpcsec_gss.c @@ -537,7 +537,7 @@ 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 --- a/sys/rpc/svc_auth.c +++ b/sys/rpc/svc_auth.c @@ -192,7 +192,7 @@ 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 @@ 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 --- a/sys/sys/ucred.h +++ b/sys/sys/ucred.h @@ -242,8 +242,8 @@ 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); /*