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