1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
| | #define _GNU_SOURCE
#include <grp.h>
#include <limits.h>
#include <errno.h>
#include <stdint.h>
#include <stdlib.h>
#undef NGROUPS_MAX
#define NGROUPS_MAX 2
int initgroups(const char *user, gid_t gid)
{
gid_t buf[NGROUPS_MAX], *groups = buf;
int count = NGROUPS_MAX, 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;
}
|