mirror of git://sourceware.org/git/glibc.git
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>
(cherry picked from commit 2f769cec44
)
This commit is contained in:
parent
61e461ed0c
commit
11e634ccf3
|
@ -21,7 +21,11 @@
|
|||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <grp.h>
|
||||
#include <scratch_buffer.h>
|
||||
#include <stdio_ext.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <support/check.h>
|
||||
#include <support/xunistd.h>
|
||||
#include <support/xsocket.h>
|
||||
|
@ -210,10 +214,48 @@ err:
|
|||
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
|
||||
support_capture_subprogram_self_sgid (const char *child_id)
|
||||
{
|
||||
gid_t target = 0;
|
||||
const int count = 64;
|
||||
gid_t groups[count];
|
||||
|
||||
|
@ -225,6 +267,7 @@ support_capture_subprogram_self_sgid (const char *child_id)
|
|||
(intmax_t) getuid ());
|
||||
|
||||
gid_t current = getgid ();
|
||||
gid_t target = current;
|
||||
for (int i = 0; i < ret; ++i)
|
||||
{
|
||||
if (groups[i] != current)
|
||||
|
@ -234,9 +277,16 @@ support_capture_subprogram_self_sgid (const char *child_id)
|
|||
}
|
||||
}
|
||||
|
||||
if (target == 0)
|
||||
FAIL_UNSUPPORTED("Could not find a suitable GID for user %jd\n",
|
||||
(intmax_t) getuid ());
|
||||
if (target == current)
|
||||
{
|
||||
/* 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);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue