#define _GNU_SOURCE #include #include #include int initgroups(const char *user, gid_t gid) { gid_t buf[32], *groups = buf; int count = sizeof buf / sizeof *buf, prev_count = count; while (getgrouplist(user, gid, groups, &count) < 0) { if (groups != buf) free(groups); /* Return if failure isn't buffer size */ if (count <= prev_count) return -1; /* Always increase by at least 50% to limit to * logarithmically many retries on TOCTOU races. */ if (count < prev_count + (prev_count>>1)) count = prev_count + (prev_count>>1); groups = calloc(count, sizeof *groups); if (!groups) return -1; prev_count = count; } int ret = setgroups(count, groups); if (groups != buf) free(groups); return ret; }