1
0
mirror of https://sourceware.org/git/glibc.git synced 2025-08-07 06:43:00 +03:00

support: Pick group in support_capture_subprogram_self_sgid if UID == 0

When running as root, it is likely that we can run under any group.
Pick a harmless group from /etc/group in this case.

Reviewed-by: Carlos O'Donell <carlos@redhat.com>
This commit is contained in:
Florian Weimer
2025-05-21 16:47:34 +02:00
parent d3e0f63fb9
commit 2f769cec44

View File

@@ -21,7 +21,11 @@
#include <errno.h> #include <errno.h>
#include <fcntl.h> #include <fcntl.h>
#include <grp.h>
#include <scratch_buffer.h>
#include <stdio_ext.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h>
#include <support/check.h> #include <support/check.h>
#include <support/xunistd.h> #include <support/xunistd.h>
#include <support/xsocket.h> #include <support/xsocket.h>
@@ -210,10 +214,48 @@ err:
return status; return status;
} }
/* Returns true if a group with NAME has been found, and writes its
GID to *TARGET. */
static bool
find_sgid_group (gid_t *target, const char *name)
{
/* Do not use getgrname_r because it does not work in statically
linked binaries if the system libc is different. */
FILE *fp = fopen ("/etc/group", "rce");
if (fp == NULL)
return false;
__fsetlocking (fp, FSETLOCKING_BYCALLER);
bool ok = false;
struct scratch_buffer buf;
scratch_buffer_init (&buf);
while (true)
{
struct group grp;
struct group *result = NULL;
int status = fgetgrent_r (fp, &grp, buf.data, buf.length, &result);
if (status == 0 && result != NULL)
{
if (strcmp (result->gr_name, name) == 0)
{
*target = result->gr_gid;
ok = true;
break;
}
}
else if (errno != ERANGE)
break;
else if (!scratch_buffer_grow (&buf))
break;
}
scratch_buffer_free (&buf);
fclose (fp);
return ok;
}
int int
support_capture_subprogram_self_sgid (const char *child_id) support_capture_subprogram_self_sgid (const char *child_id)
{ {
gid_t target = 0;
const int count = 64; const int count = 64;
gid_t groups[count]; gid_t groups[count];
@@ -225,6 +267,7 @@ support_capture_subprogram_self_sgid (const char *child_id)
(intmax_t) getuid ()); (intmax_t) getuid ());
gid_t current = getgid (); gid_t current = getgid ();
gid_t target = current;
for (int i = 0; i < ret; ++i) for (int i = 0; i < ret; ++i)
{ {
if (groups[i] != current) if (groups[i] != current)
@@ -234,9 +277,16 @@ support_capture_subprogram_self_sgid (const char *child_id)
} }
} }
if (target == 0) if (target == current)
FAIL_UNSUPPORTED("Could not find a suitable GID for user %jd\n", {
(intmax_t) getuid ()); /* If running as root, try to find a harmless group for SGID. */
if (getuid () != 0
|| (!find_sgid_group (&target, "nogroup")
&& !find_sgid_group (&target, "bin")
&& !find_sgid_group (&target, "daemon")))
FAIL_UNSUPPORTED("Could not find a suitable GID for user %jd\n",
(intmax_t) getuid ());
}
return copy_and_spawn_sgid (child_id, target); return copy_and_spawn_sgid (child_id, target);
} }