xref: /aosp_15_r20/external/musl/src/misc/initgroups.c (revision c9945492fdd68bbe62686c5b452b4dc1be3f8453)
1 #define _GNU_SOURCE
2 #include <grp.h>
3 #include <limits.h>
4 #include <stdlib.h>
5 
initgroups(const char * user,gid_t gid)6 int 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