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 @@ -2456,6 +2456,24 @@ groups_normalize(&cr->cr_ngroups, cr->cr_groups); } +/* + * Same as crsetgroups() but accepts an empty groups array. + * + * This function ensures that an effective GID is always present in credentials. + * An empty array is treated as a one-size one holding the passed effective GID + * fallback. + */ +void +crsetgroups_empty_fallback(struct ucred *cr, int ngrp, const gid_t *groups, + const gid_t fallback) +{ + if (ngrp == 0) + /* Shortcut. */ + crsetgroups_internal(cr, 1, &fallback); + else + crsetgroups(cr, ngrp, groups); +} + /* * Get login name, if available. */ diff --git a/sys/sys/ucred.h b/sys/sys/ucred.h --- a/sys/sys/ucred.h +++ b/sys/sys/ucred.h @@ -165,6 +165,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_empty_fallback(struct ucred *cr, int ngrp, + const gid_t *groups, const gid_t fallback); /* * Returns whether gid designates a primary group in cred.