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 @@ -2796,7 +2796,8 @@ size_t nbytes; MPASS2(cr->cr_ref == 1, "'cr_ref' must be 1 (referenced, unshared)"); - MPASS2(cr->cr_ngroups == 0, "groups on 'cr' already set!"); + MPASS2((cr->cr_flags & CRED_FLAG_GROUPSET) == 0, + "groups on 'cr' already set!"); groups_check_positive_len(n); groups_check_max_len(n); @@ -2890,6 +2891,7 @@ bcopy(groups, cr->cr_groups, ngrp * sizeof(gid_t)); cr->cr_ngroups = ngrp; + cr->cr_flags |= CRED_FLAG_GROUPSET; } /* @@ -2906,15 +2908,19 @@ if (ngrp > ngroups_max) ngrp = ngroups_max; + cr->cr_ngroups = 0; + if (ngrp == 0) { + cr->cr_flags |= CRED_FLAG_GROUPSET; + return; + } + /* * crextend() asserts that groups are not set, as it may allocate a new * backing storage without copying the content of the old one. Since we * are going to install a completely new set anyway, signal that we * consider the old ones thrown away. */ - cr->cr_ngroups = 0; - if (ngrp == 0) - return; + cr->cr_flags &= ~CRED_FLAG_GROUPSET; crextend(cr, ngrp); crsetgroups_internal(cr, ngrp, groups); @@ -2936,6 +2942,7 @@ if (ngrp == 0) { cr->cr_gid = fallback; cr->cr_ngroups = 0; + cr->cr_flags |= CRED_FLAG_GROUPSET; return; } diff --git a/sys/sys/ucred.h b/sys/sys/ucred.h --- a/sys/sys/ucred.h +++ b/sys/sys/ucred.h @@ -44,6 +44,7 @@ * Flags for cr_flags. */ #define CRED_FLAG_CAPMODE 0x00000001 /* In capability mode. */ +#define CRED_FLAG_GROUPSET 0x00000002 /* Groups have been set. */ /* * Number of groups inlined in 'struct ucred'. It must stay reasonably low as