From: Ismail Ramzi <[email protected]>

* src/chroot.c (main): When the primary group was inferred from the
uid outside the chroot, let a successful getpwuid() inside the chroot
replace it, as is already done for the uid and supplemental groups.
Previously the gid found outside persisted, so for example
'chroot --userspec=alice NEWROOT' ran with alice's uid from NEWROOT
but alice's gid from the host.
* NEWS: Mention the bug fix.

Link: https://github.com/coreutils/coreutils/pull/363
---
 NEWS         |  5 +++++
 src/chroot.c | 12 +++++++++---
 2 files changed, 14 insertions(+), 3 deletions(-)

diff --git a/NEWS b/NEWS
index 7af271ceb..72f904eee 100644
--- a/NEWS
+++ b/NEWS
@@ -4,6 +4,11 @@ GNU coreutils NEWS                                    -*- 
outline -*-
 
 ** Bug fixes
 
+  'chroot --userspec=USER' now uses the primary group of USER as looked up
+  inside the chroot.  Previously the group looked up outside the chroot
+  was used, even when the look-up inside the chroot succeeded.
+  [bug introduced in coreutils-8.23]
+
   cut, expand, fold, join, numfmt, unexpand, and uniq, no longer consider
   the \u0085 (next line) character as a separator on non-GLIBC platforms.
   [bug introduced in coreutils-9.11]
diff --git a/src/chroot.c b/src/chroot.c
index 8ee41e4e9..cad94264e 100644
--- a/src/chroot.c
+++ b/src/chroot.c
@@ -228,6 +228,9 @@ main (int argc, char **argv)
   /* Parsed user and group IDs.  */
   uid_t uid = -1;
   gid_t gid = -1;
+  /* Whether GID was inferred from UID outside the chroot,
+     in which case a look-up inside the chroot takes precedence.  */
+  bool gid_inferred = false;
   GETGROUPS_T *out_gids = NULL;
   idx_t n_gids = 0;
 
@@ -308,7 +311,10 @@ main (int argc, char **argv)
           if ((pwd = getpwuid (uid)))
             {
               if (gid_unset (gid))
-                gid = pwd->pw_gid;
+                {
+                  gid = pwd->pw_gid;
+                  gid_inferred = true;
+                }
               username = pwd->pw_name;
             }
         }
@@ -362,12 +368,12 @@ main (int argc, char **argv)
 
   /* If no gid is supplied or looked up, do so now.
      Also lookup the username for use with getgroups.  */
-  if (uid_set (uid) && (! groups || gid_unset (gid)))
+  if (uid_set (uid) && (! groups || gid_unset (gid) || gid_inferred))
     {
       const struct passwd *pwd;
       if ((pwd = getpwuid (uid)))
         {
-          if (gid_unset (gid))
+          if (gid_unset (gid) || gid_inferred)
             gid = pwd->pw_gid;
           username = pwd->pw_name;
         }
-- 
2.55.0


Reply via email to