The branch main has been updated by kevans:

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

commit babab49eee9472f628d774996de13d13d296c8c0
Author:     Kyle Evans <kev...@freebsd.org>
AuthorDate: 2025-08-12 12:14:38 +0000
Commit:     Kyle Evans <kev...@freebsd.org>
CommitDate: 2025-08-12 12:30:23 +0000

    chroot: don't setgroups() without -G having been specified
    
    We previously would not have setgroups() at all, but now we would drop
    our supplementary groups every time.  This broke chroot -n, probably
    among other things.  We need tests here, but lets unbreak things first.
    
    A future change may try to setgroups(2) when -u is specified in addition
    to -G, so predicate the call on gidlist and don't populate that without
    a grouplist.
    
    PR:             288751
    Fixes:  48fd05999b0f ("chroot: don't clobber the egid [...]")
---
 usr.sbin/chroot/chroot.c | 43 ++++++++++++++++++++++++++-----------------
 1 file changed, 26 insertions(+), 17 deletions(-)

diff --git a/usr.sbin/chroot/chroot.c b/usr.sbin/chroot/chroot.c
index d9fb29474d87..7ec5a00b50f0 100644
--- a/usr.sbin/chroot/chroot.c
+++ b/usr.sbin/chroot/chroot.c
@@ -103,7 +103,9 @@ main(int argc, char *argv[])
 
        gid = 0;
        uid = 0;
+       gids = 0;
        user = group = grouplist = NULL;
+       gidlist = NULL;
        nonprivileged = false;
        while ((ch = getopt(argc, argv, "G:g:u:n")) != -1) {
                switch(ch) {
@@ -119,6 +121,11 @@ main(int argc, char *argv[])
                        break;
                case 'G':
                        grouplist = optarg;
+
+                       /*
+                        * XXX Why not allow us to drop all of our supplementary
+                        * groups?
+                        */
                        if (*grouplist == '\0')
                                usage();
                        break;
@@ -139,23 +146,25 @@ main(int argc, char *argv[])
        if (group != NULL)
                gid = resolve_group(group);
 
-       ngroups_max = sysconf(_SC_NGROUPS_MAX) + 1;
-       if ((gidlist = malloc(sizeof(gid_t) * ngroups_max)) == NULL)
-               err(1, "malloc");
-       /* Populate the egid slot in our groups to avoid accidents. */
-       if (gid == 0)
-               gidlist[0] = getegid();
-       else
-               gidlist[0] = gid;
-       for (gids = 1;
-           (p = strsep(&grouplist, ",")) != NULL && gids < ngroups_max; ) {
-               if (*p == '\0')
-                       continue;
-
-               gidlist[gids++] = resolve_group(p);
+       if (grouplist != NULL) {
+               ngroups_max = sysconf(_SC_NGROUPS_MAX) + 1;
+               if ((gidlist = malloc(sizeof(gid_t) * ngroups_max)) == NULL)
+                       err(1, "malloc");
+               /* Populate the egid slot in our groups to avoid accidents. */
+               if (gid == 0)
+                       gidlist[0] = getegid();
+               else
+                       gidlist[0] = gid;
+               for (gids = 1; (p = strsep(&grouplist, ",")) != NULL &&
+                   gids < ngroups_max; ) {
+                       if (*p == '\0')
+                               continue;
+
+                       gidlist[gids++] = resolve_group(p);
+               }
+               if (p != NULL && gids == ngroups_max)
+                       errx(1, "too many supplementary groups provided");
        }
-       if (p != NULL && gids == ngroups_max)
-               errx(1, "too many supplementary groups provided");
 
        if (user != NULL)
                uid = resolve_user(user);
@@ -175,7 +184,7 @@ main(int argc, char *argv[])
                err(1, "%s", argv[0]);
        }
 
-       if (gids && setgroups(gids, gidlist) == -1)
+       if (gidlist != NULL && setgroups(gids, gidlist) == -1)
                err(1, "setgroups");
        if (group && setgid(gid) == -1)
                err(1, "setgid");

Reply via email to