diff options
author | Yu Watanabe <watanabe.yu+github@gmail.com> | 2019-11-03 22:54:32 +0900 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-11-03 22:54:32 +0900 |
commit | f4dad55b8b2861426a7b9e7104dec33acb770894 (patch) | |
tree | 193667d60c5d857dbc4fa3f9a81edd575efc6366 /src | |
parent | 5e467d74ad0c87f1f5e1a1e58bdce7b1971dd7a3 (diff) | |
parent | eb2cfa81b005264693cc15d156995f9c31034196 (diff) | |
download | systemd-f4dad55b8b2861426a7b9e7104dec33acb770894.tar.gz |
Merge pull request #13899 from poettering/in-gid-tweak
user-util: tweak to in_gid()
Diffstat (limited to 'src')
-rw-r--r-- | src/basic/user-util.c | 50 | ||||
-rw-r--r-- | src/test/test-user-util.c | 11 |
2 files changed, 45 insertions, 16 deletions
diff --git a/src/basic/user-util.c b/src/basic/user-util.c index 7a31a69e36..b5fdfafd61 100644 --- a/src/basic/user-util.c +++ b/src/basic/user-util.c @@ -409,8 +409,10 @@ char* gid_to_name(gid_t gid) { } int in_gid(gid_t gid) { - gid_t *gids; - int ngroups, r, i; + _cleanup_free_ gid_t *allocated = NULL; + gid_t local[16], *p = local; + int ngroups = ELEMENTSOF(local); + unsigned attempt = 0; if (getgid() == gid) return 1; @@ -421,23 +423,39 @@ int in_gid(gid_t gid) { if (!gid_is_valid(gid)) return -EINVAL; - ngroups = getgroups(0, NULL); - if (ngroups < 0) - return -errno; - if (ngroups == 0) - return 0; - - gids = newa(gid_t, ngroups); + for (;;) { + ngroups = getgroups(ngroups, p); + if (ngroups >= 0) + break; + if (errno != EINVAL) + return -errno; + + /* Give up eventually */ + if (attempt++ > 10) + return -EINVAL; + + /* Get actual size needed, and size the array explicitly. Note that this is potentially racy + * to use (in multi-threaded programs), hence let's call this in a loop. */ + ngroups = getgroups(0, NULL); + if (ngroups < 0) + return -errno; + if (ngroups == 0) + return false; + + free(allocated); + + allocated = new(gid_t, ngroups); + if (!allocated) + return -ENOMEM; - r = getgroups(ngroups, gids); - if (r < 0) - return -errno; + p = allocated; + } - for (i = 0; i < r; i++) - if (gids[i] == gid) - return 1; + for (int i = 0; i < ngroups; i++) + if (p[i] == gid) + return true; - return 0; + return false; } int in_group(const char *name) { diff --git a/src/test/test-user-util.c b/src/test/test-user-util.c index 9475b99c28..47baacb518 100644 --- a/src/test/test-user-util.c +++ b/src/test/test-user-util.c @@ -286,6 +286,15 @@ static void test_make_salt(void) { assert(!streq(s, t)); } +static void test_in_gid(void) { + + assert(in_gid(getgid()) >= 0); + assert(in_gid(getegid()) >= 0); + + assert(in_gid(GID_INVALID) < 0); + assert(in_gid(TTY_GID) == 0); /* The TTY gid is for owning ttys, it would be really really weird if we were in it. */ +} + int main(int argc, char *argv[]) { test_uid_to_name_one(0, "root"); test_uid_to_name_one(UID_NOBODY, NOBODY_USER_NAME); @@ -320,5 +329,7 @@ int main(int argc, char *argv[]) { test_make_salt(); + test_in_gid(); + return 0; } |