chroot: prefer the in-chroot primary group with --userspec=USER

* 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
This commit is contained in:
Ismail Ramzi authored and Pádraig Brady committed 2026-10-07 12:33:14 +01:00
1 parent 9a38bb9186
commit b9776257e8
2 files changed
+14 -3

No files matched your search

+5
View File
@@ -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]
+9 -3
View File
@@ -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;
}