mirror of
https://git.busybox.net/busybox
synced 2025-05-10 04:33:59 +02:00
Testcase: setuidgid 1:1 strace ash -c 'test -x TODO; test -x TODO; echo $?' should show that second "test -x" does not query ids again. function old new delta ash_main 1236 1256 +20 get_cached_euid - 19 +19 get_cached_egid - 19 +19 test_main 56 72 +16 test_exec 119 135 +16 is_in_supplementary_groups 52 57 +5 nexpr 718 702 -16 ------------------------------------------------------------------------------ (add/remove: 2/0 grow/shrink: 4/1 up/down: 95/-16) Total: 79 bytes Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
81 lines
1.8 KiB
C
81 lines
1.8 KiB
C
/*
|
|
* Utility routines.
|
|
*
|
|
* Copyright (C) 2017 Denys Vlasenko
|
|
*
|
|
* Licensed under GPLv2, see file LICENSE in this source tree.
|
|
*/
|
|
|
|
//kbuild:lib-y += bb_getgroups.o
|
|
|
|
#include "libbb.h"
|
|
|
|
gid_t* FAST_FUNC bb_getgroups(int *ngroups, gid_t *group_array)
|
|
{
|
|
int n = ngroups ? *ngroups : 0;
|
|
|
|
/* getgroups may be a bit expensive, try to use it only once */
|
|
if (n < 32)
|
|
n = 32;
|
|
|
|
for (;;) {
|
|
// FIXME: ash tries so hard to not die on OOM (when we are called from test),
|
|
// and we spoil it with just one xrealloc here
|
|
group_array = xrealloc(group_array, (n+1) * sizeof(group_array[0]));
|
|
n = getgroups(n, group_array);
|
|
/*
|
|
* If buffer is too small, kernel does not return new_n > n.
|
|
* It returns -1 and EINVAL:
|
|
*/
|
|
if (n >= 0) {
|
|
/* Terminator for bb_getgroups(NULL, NULL) usage */
|
|
group_array[n] = (gid_t) -1;
|
|
break;
|
|
}
|
|
if (errno == EINVAL) { /* too small? */
|
|
/* This is the way to ask kernel how big the array is */
|
|
n = getgroups(0, group_array);
|
|
continue;
|
|
}
|
|
/* Some other error (should never happen on Linux) */
|
|
bb_simple_perror_msg_and_die("getgroups");
|
|
}
|
|
|
|
if (ngroups)
|
|
*ngroups = n;
|
|
return group_array;
|
|
}
|
|
|
|
uid_t FAST_FUNC get_cached_euid(uid_t *euid)
|
|
{
|
|
if (*euid == (uid_t)-1)
|
|
*euid = geteuid();
|
|
return *euid;
|
|
}
|
|
|
|
gid_t FAST_FUNC get_cached_egid(gid_t *egid)
|
|
{
|
|
if (*egid == (gid_t)-1)
|
|
*egid = getegid();
|
|
return *egid;
|
|
}
|
|
|
|
/* Return non-zero if GID is in our supplementary group list. */
|
|
int FAST_FUNC is_in_supplementary_groups(struct cached_groupinfo *groupinfo, gid_t gid)
|
|
{
|
|
int i;
|
|
int ngroups;
|
|
gid_t *group_array;
|
|
|
|
if (groupinfo->ngroups == 0)
|
|
groupinfo->supplementary_array = bb_getgroups(&groupinfo->ngroups, NULL);
|
|
ngroups = groupinfo->ngroups;
|
|
group_array = groupinfo->supplementary_array;
|
|
|
|
/* Search through the list looking for GID. */
|
|
for (i = 0; i < ngroups; i++)
|
|
if (gid == group_array[i])
|
|
return 1;
|
|
|
|
return 0;
|
|
}
|