1 #define _GNU_SOURCE 2 #include <grp.h> 3 #include <limits.h> 4 #include <stdlib.h> 5 initgroups(const char * user,gid_t gid)6int initgroups(const char *user, gid_t gid) 7 { 8 gid_t buf[32], *groups = buf; 9 int count = sizeof buf / sizeof *buf, prev_count = count; 10 while (getgrouplist(user, gid, groups, &count) < 0) { 11 if (groups != buf) free(groups); 12 13 /* Return if failure isn't buffer size */ 14 if (count <= prev_count) 15 return -1; 16 17 /* Always increase by at least 50% to limit to 18 * logarithmically many retries on TOCTOU races. */ 19 if (count < prev_count + (prev_count>>1)) 20 count = prev_count + (prev_count>>1); 21 22 groups = calloc(count, sizeof *groups); 23 if (!groups) return -1; 24 prev_count = count; 25 } 26 int ret = setgroups(count, groups); 27 if (groups != buf) free(groups); 28 return ret; 29 } 30