The branch main has been updated by kevans:

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

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

    kern: add a new ucred flag for groups having been set
    
    Now that we can legitimately have ngroups == 0 as a result of calling
    crsetgroups(), set a flag when we've set groups for the sake of sanity
    checking usage of crextend().  While it's true this flag will only
    really be used under INVARIANTS, it's only the second flag bit that
    we're adding in 16 years.
    
    Reviewed by:    olce
    Differential Revision:  https://reviews.freebsd.org/D51646
---
 sys/compat/linux/linux_misc.c  |  1 +
 sys/compat/linux/linux_uid16.c |  1 +
 sys/kern/kern_prot.c           | 15 +++++++++++----
 sys/sys/ucred.h                |  1 +
 4 files changed, 14 insertions(+), 4 deletions(-)

diff --git a/sys/compat/linux/linux_misc.c b/sys/compat/linux/linux_misc.c
index 31460819e6ab..5e32353c6b8e 100644
--- a/sys/compat/linux/linux_misc.c
+++ b/sys/compat/linux/linux_misc.c
@@ -1056,6 +1056,7 @@ linux_setgroups(struct thread *td, struct 
linux_setgroups_args *args)
        newcred->cr_ngroups = ngrp;
        for (int i = 0; i < ngrp; i++)
                newcred->cr_groups[i] = linux_gidset[i];
+       newcred->cr_flags |= CRED_FLAG_GROUPSET;
 
        setsugid(p);
        proc_set_cred(p, newcred);
diff --git a/sys/compat/linux/linux_uid16.c b/sys/compat/linux/linux_uid16.c
index 9fe799c0b9de..1d9a19916412 100644
--- a/sys/compat/linux/linux_uid16.c
+++ b/sys/compat/linux/linux_uid16.c
@@ -117,6 +117,7 @@ linux_setgroups16(struct thread *td, struct 
linux_setgroups16_args *args)
        newcred->cr_ngroups = ngrp;
        for (int i = 0; i < ngrp; i++)
                newcred->cr_groups[i] = linux_gidset[i];
+       newcred->cr_flags |= CRED_FLAG_GROUPSET;
 
        setsugid(td->td_proc);
        proc_set_cred(p, newcred);
diff --git a/sys/kern/kern_prot.c b/sys/kern/kern_prot.c
index 48ab7c0b520b..632be229af5b 100644
--- a/sys/kern/kern_prot.c
+++ b/sys/kern/kern_prot.c
@@ -2796,7 +2796,8 @@ crextend(struct ucred *cr, int n)
        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 @@ crsetgroups_internal(struct ucred *cr, int ngrp, const 
gid_t *groups)
 
        bcopy(groups, cr->cr_groups, ngrp * sizeof(gid_t));
        cr->cr_ngroups = ngrp;
+       cr->cr_flags |= CRED_FLAG_GROUPSET;
 }
 
 /*
@@ -2906,15 +2908,19 @@ crsetgroups(struct ucred *cr, int ngrp, const gid_t 
*groups)
 
        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 @@ crsetgroups_fallback(struct ucred *cr, int ngrp, const 
gid_t *groups,
        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
index 4831d8cb6e1b..cd4efcb71c0d 100644
--- 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

Reply via email to