From 7e5a584f0cd7f5d333da5f68e110a75271d8f40d Mon Sep 17 00:00:00 2001 From: Stephen Heumann Date: Tue, 4 Nov 2014 16:24:41 -0600 Subject: [PATCH] Use alternative code (also from BusyBox) for checking if the user is in a group, avoiding a call to getgroups(), which isn't supported. This could actually be further simplified, since GNO doesn't really have group-based file permissions, but I'll leave that until later. --- coreutils/test.c | 52 +++-------------------------------------------- include/libbb.h | 2 ++ libbb/appletlib.c | 15 ++++++++++++++ 3 files changed, 20 insertions(+), 49 deletions(-) diff --git a/coreutils/test.c b/coreutils/test.c index d2f3b1216..4dc36e8a9 100644 --- a/coreutils/test.c +++ b/coreutils/test.c @@ -390,8 +390,6 @@ struct test_statics { /* set only by check_operator(), either to bogus struct * or points to matching operator_t struct. Never NULL. */ const struct operator_t *last_operator; - gid_t *group_array; - int ngroups; jmp_buf leaving; }; @@ -401,8 +399,6 @@ extern struct test_statics *const test_ptr_to_statics; #define S (*test_ptr_to_statics) #define args (S.args ) #define last_operator (S.last_operator) -#define group_array (S.group_array ) -#define ngroups (S.ngroups ) #define leaving (S.leaving ) #define INIT_S() do { \ @@ -561,46 +557,14 @@ static int binop(void) } -static void initialize_group_array(void) -{ - int n; - - /* getgroups may be expensive, try to use it only once */ - ngroups = 32; - do { - /* FIXME: ash tries so hard to not die on OOM, - * and we spoil it with just one xrealloc here */ - /* We realloc, because test_main can be entered repeatedly by shell. - * Testcase (ash): 'while true; do test -x some_file; done' - * and watch top. (some_file must have owner != you) */ - n = ngroups; - group_array = xrealloc(group_array, n * sizeof(gid_t)); - ngroups = getgroups(n, group_array); - } while (ngroups > n); -} - - /* Return non-zero if GID is one that we have in our groups list. */ -//XXX: FIXME: duplicate of existing libbb function? -// see toplevel TODO file: -// possible code duplication ingroup() and is_a_group_member() static int is_a_group_member(gid_t gid) { - int i; - - /* Short-circuit if possible, maybe saving a call to getgroups(). */ + /* Short-circuit if possible */ if (gid == getgid() || gid == getegid()) return 1; - - if (ngroups == 0) - initialize_group_array(); - - /* Search through the list looking for GID. */ - for (i = 0; i < ngroups; i++) - if (gid == group_array[i]) - return 1; - - return 0; + + return ingroup(getuid(), gid) || ingroup(geteuid(), gid); } @@ -863,16 +827,6 @@ int test_main(int argc, char **argv) if (res) goto ret; - /* resetting ngroups is probably unnecessary. it will - * force a new call to getgroups(), which prevents using - * group data fetched during a previous call. but the - * only way the group data could be stale is if there's - * been an intervening call to setgroups(), and this - * isn't likely in the case of a shell. paranoia - * prevails... - */ - /*ngroups = 0; - done by INIT_S() */ - argv++; args = argv; diff --git a/include/libbb.h b/include/libbb.h index 7ec6ef28f..90b566abd 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -841,6 +841,8 @@ void die_if_bad_username(const char* name) FAST_FUNC; #define die_if_bad_username(name) ((void)(name)) #endif +int ingroup(uid_t u, gid_t g); + #if ENABLE_FEATURE_UTMP void FAST_FUNC write_new_utmp(pid_t pid, int new_type, const char *tty_name, const char *username, const char *hostname); void FAST_FUNC update_utmp(pid_t pid, int new_type, const char *tty_name, const char *username, const char *hostname); diff --git a/libbb/appletlib.c b/libbb/appletlib.c index 1852da245..1d70b7358 100644 --- a/libbb/appletlib.c +++ b/libbb/appletlib.c @@ -18,3 +18,18 @@ void FAST_FUNC bb_show_usage(void) { xfunc_die(); } + +/* check if u is member of group g */ +int ingroup(uid_t u, gid_t g) +{ + struct group *grp = getgrgid(g); + if (grp) { + char **mem; + for (mem = grp->gr_mem; *mem; mem++) { + struct passwd *pwd = getpwnam(*mem); + if (pwd && (pwd->pw_uid == u)) + return 1; + } + } + return 0; +}