11182St.nateldemoura@f5.com /*
21182St.nateldemoura@f5.com * Copyright (C) Igor Sysoev
31182St.nateldemoura@f5.com * Copyright (C) NGINX, Inc.
41182St.nateldemoura@f5.com */
51182St.nateldemoura@f5.com
61182St.nateldemoura@f5.com #include <nxt_main.h>
71182St.nateldemoura@f5.com #include <sys/types.h>
81182St.nateldemoura@f5.com #include <nxt_conf.h>
91182St.nateldemoura@f5.com #include <nxt_clone.h>
101182St.nateldemoura@f5.com
111182St.nateldemoura@f5.com
121182St.nateldemoura@f5.com #if (NXT_HAVE_CLONE_NEWUSER)
131182St.nateldemoura@f5.com
141306St.nateldemoura@f5.com nxt_int_t nxt_clone_credential_setgroups(nxt_task_t *task, pid_t child_pid,
151182St.nateldemoura@f5.com const char *str);
161306St.nateldemoura@f5.com nxt_int_t nxt_clone_credential_map_set(nxt_task_t *task, const char* mapfile,
171306St.nateldemoura@f5.com pid_t pid, nxt_int_t default_container, nxt_int_t default_host,
181306St.nateldemoura@f5.com nxt_clone_credential_map_t *map);
191306St.nateldemoura@f5.com nxt_int_t nxt_clone_credential_map_write(nxt_task_t *task, const char *mapfile,
201182St.nateldemoura@f5.com pid_t pid, u_char *mapinfo);
211182St.nateldemoura@f5.com
221182St.nateldemoura@f5.com
231182St.nateldemoura@f5.com nxt_int_t
nxt_clone_credential_setgroups(nxt_task_t * task,pid_t child_pid,const char * str)241306St.nateldemoura@f5.com nxt_clone_credential_setgroups(nxt_task_t *task, pid_t child_pid,
251306St.nateldemoura@f5.com const char *str)
261182St.nateldemoura@f5.com {
271182St.nateldemoura@f5.com int fd, n;
281182St.nateldemoura@f5.com u_char *p, *end;
291182St.nateldemoura@f5.com u_char path[PATH_MAX];
301182St.nateldemoura@f5.com
311182St.nateldemoura@f5.com end = path + PATH_MAX;
321182St.nateldemoura@f5.com p = nxt_sprintf(path, end, "/proc/%d/setgroups", child_pid);
331182St.nateldemoura@f5.com *p = '\0';
341182St.nateldemoura@f5.com
351182St.nateldemoura@f5.com if (nxt_slow_path(p == end)) {
361182St.nateldemoura@f5.com nxt_alert(task, "error write past the buffer: %s", path);
371182St.nateldemoura@f5.com return NXT_ERROR;
381182St.nateldemoura@f5.com }
391182St.nateldemoura@f5.com
401182St.nateldemoura@f5.com fd = open((char *)path, O_RDWR);
411182St.nateldemoura@f5.com
421182St.nateldemoura@f5.com if (fd == -1) {
431182St.nateldemoura@f5.com /*
441182St.nateldemoura@f5.com * If the /proc/pid/setgroups doesn't exists, we are
451182St.nateldemoura@f5.com * safe to set uid/gid maps. But if the error is anything
461182St.nateldemoura@f5.com * other than ENOENT, then we should abort and let user know.
471182St.nateldemoura@f5.com */
481182St.nateldemoura@f5.com
491182St.nateldemoura@f5.com if (errno != ENOENT) {
501182St.nateldemoura@f5.com nxt_alert(task, "open(%s): %E", path, nxt_errno);
511182St.nateldemoura@f5.com return NXT_ERROR;
521182St.nateldemoura@f5.com }
531182St.nateldemoura@f5.com
541182St.nateldemoura@f5.com return NXT_OK;
551182St.nateldemoura@f5.com }
561182St.nateldemoura@f5.com
571182St.nateldemoura@f5.com n = write(fd, str, strlen(str));
581182St.nateldemoura@f5.com close(fd);
591182St.nateldemoura@f5.com
601182St.nateldemoura@f5.com if (nxt_slow_path(n == -1)) {
611182St.nateldemoura@f5.com nxt_alert(task, "write(%s): %E", path, nxt_errno);
621182St.nateldemoura@f5.com return NXT_ERROR;
631182St.nateldemoura@f5.com }
641182St.nateldemoura@f5.com
651182St.nateldemoura@f5.com return NXT_OK;
661182St.nateldemoura@f5.com }
671182St.nateldemoura@f5.com
681182St.nateldemoura@f5.com
691182St.nateldemoura@f5.com nxt_int_t
nxt_clone_credential_map_write(nxt_task_t * task,const char * mapfile,pid_t pid,u_char * mapinfo)701306St.nateldemoura@f5.com nxt_clone_credential_map_write(nxt_task_t *task, const char *mapfile,
711306St.nateldemoura@f5.com pid_t pid, u_char *mapinfo)
721182St.nateldemoura@f5.com {
731182St.nateldemoura@f5.com int len, mapfd;
741182St.nateldemoura@f5.com u_char *p, *end;
751182St.nateldemoura@f5.com ssize_t n;
761182St.nateldemoura@f5.com u_char buf[256];
771182St.nateldemoura@f5.com
781182St.nateldemoura@f5.com end = buf + sizeof(buf);
791182St.nateldemoura@f5.com
801182St.nateldemoura@f5.com p = nxt_sprintf(buf, end, "/proc/%d/%s", pid, mapfile);
811182St.nateldemoura@f5.com if (nxt_slow_path(p == end)) {
821182St.nateldemoura@f5.com nxt_alert(task, "writing past the buffer");
831182St.nateldemoura@f5.com return NXT_ERROR;
841182St.nateldemoura@f5.com }
851182St.nateldemoura@f5.com
861182St.nateldemoura@f5.com *p = '\0';
871182St.nateldemoura@f5.com
881182St.nateldemoura@f5.com mapfd = open((char*)buf, O_RDWR);
891182St.nateldemoura@f5.com if (nxt_slow_path(mapfd == -1)) {
901182St.nateldemoura@f5.com nxt_alert(task, "failed to open proc map (%s) %E", buf, nxt_errno);
911182St.nateldemoura@f5.com return NXT_ERROR;
921182St.nateldemoura@f5.com }
931182St.nateldemoura@f5.com
941182St.nateldemoura@f5.com len = nxt_strlen(mapinfo);
951182St.nateldemoura@f5.com
961182St.nateldemoura@f5.com n = write(mapfd, (char *)mapinfo, len);
971182St.nateldemoura@f5.com if (nxt_slow_path(n != len)) {
981182St.nateldemoura@f5.com
991182St.nateldemoura@f5.com if (n == -1 && nxt_errno == EINVAL) {
1001182St.nateldemoura@f5.com nxt_alert(task, "failed to write %s: Check kernel maximum " \
1011182St.nateldemoura@f5.com "allowed lines %E", buf, nxt_errno);
1021182St.nateldemoura@f5.com
1031182St.nateldemoura@f5.com } else {
1041182St.nateldemoura@f5.com nxt_alert(task, "failed to write proc map (%s) %E", buf,
1051182St.nateldemoura@f5.com nxt_errno);
1061182St.nateldemoura@f5.com }
1071182St.nateldemoura@f5.com
1081201St.nateldemoura@f5.com close(mapfd);
1091201St.nateldemoura@f5.com
1101182St.nateldemoura@f5.com return NXT_ERROR;
1111182St.nateldemoura@f5.com }
1121182St.nateldemoura@f5.com
1131201St.nateldemoura@f5.com close(mapfd);
1141201St.nateldemoura@f5.com
1151182St.nateldemoura@f5.com return NXT_OK;
1161182St.nateldemoura@f5.com }
1171182St.nateldemoura@f5.com
1181182St.nateldemoura@f5.com
1191182St.nateldemoura@f5.com nxt_int_t
nxt_clone_credential_map_set(nxt_task_t * task,const char * mapfile,pid_t pid,nxt_int_t default_container,nxt_int_t default_host,nxt_clone_credential_map_t * map)1201306St.nateldemoura@f5.com nxt_clone_credential_map_set(nxt_task_t *task, const char* mapfile, pid_t pid,
1211306St.nateldemoura@f5.com nxt_int_t default_container, nxt_int_t default_host,
1221306St.nateldemoura@f5.com nxt_clone_credential_map_t *map)
1231182St.nateldemoura@f5.com {
1241306St.nateldemoura@f5.com u_char *p, *end, *mapinfo;
1251306St.nateldemoura@f5.com nxt_int_t ret, len;
1261306St.nateldemoura@f5.com nxt_uint_t i;
1271182St.nateldemoura@f5.com
1281182St.nateldemoura@f5.com /*
1291182St.nateldemoura@f5.com * uid_map one-entry size:
1301182St.nateldemoura@f5.com * alloc space for 3 numbers (32bit) plus 2 spaces and \n.
1311182St.nateldemoura@f5.com */
1321182St.nateldemoura@f5.com len = sizeof(u_char) * (10 + 10 + 10 + 2 + 1);
1331182St.nateldemoura@f5.com
1341306St.nateldemoura@f5.com if (map->size > 0) {
1351306St.nateldemoura@f5.com len = len * map->size + 1;
1361182St.nateldemoura@f5.com
1371182St.nateldemoura@f5.com mapinfo = nxt_malloc(len);
1381182St.nateldemoura@f5.com if (nxt_slow_path(mapinfo == NULL)) {
1391182St.nateldemoura@f5.com return NXT_ERROR;
1401182St.nateldemoura@f5.com }
1411182St.nateldemoura@f5.com
1421182St.nateldemoura@f5.com p = mapinfo;
1431182St.nateldemoura@f5.com end = mapinfo + len;
1441182St.nateldemoura@f5.com
1451306St.nateldemoura@f5.com for (i = 0; i < map->size; i++) {
146*2629Sa.clayton@nginx.com p = nxt_sprintf(p, end, "%L %L %L", map->map[i].container,
1471306St.nateldemoura@f5.com map->map[i].host, map->map[i].size);
1481182St.nateldemoura@f5.com
1491182St.nateldemoura@f5.com if (nxt_slow_path(p == end)) {
1501306St.nateldemoura@f5.com nxt_alert(task, "write past the mapinfo buffer");
1511182St.nateldemoura@f5.com nxt_free(mapinfo);
1521182St.nateldemoura@f5.com return NXT_ERROR;
1531182St.nateldemoura@f5.com }
1541182St.nateldemoura@f5.com
1552617Szelenkov@nginx.com if (i + 1 < map->size) {
1561182St.nateldemoura@f5.com *p++ = '\n';
1571182St.nateldemoura@f5.com
1581182St.nateldemoura@f5.com } else {
1591182St.nateldemoura@f5.com *p = '\0';
1601182St.nateldemoura@f5.com }
1611182St.nateldemoura@f5.com }
1621182St.nateldemoura@f5.com
1631182St.nateldemoura@f5.com } else {
1641182St.nateldemoura@f5.com mapinfo = nxt_malloc(len);
1651182St.nateldemoura@f5.com if (nxt_slow_path(mapinfo == NULL)) {
1661182St.nateldemoura@f5.com return NXT_ERROR;
1671182St.nateldemoura@f5.com }
1681182St.nateldemoura@f5.com
1691182St.nateldemoura@f5.com end = mapinfo + len;
1701306St.nateldemoura@f5.com p = nxt_sprintf(mapinfo, end, "%d %d 1",
1711306St.nateldemoura@f5.com default_container, default_host);
1721182St.nateldemoura@f5.com *p = '\0';
1731182St.nateldemoura@f5.com
1741182St.nateldemoura@f5.com if (nxt_slow_path(p == end)) {
1751306St.nateldemoura@f5.com nxt_alert(task, "write past mapinfo buffer");
1761182St.nateldemoura@f5.com nxt_free(mapinfo);
1771182St.nateldemoura@f5.com return NXT_ERROR;
1781182St.nateldemoura@f5.com }
1791182St.nateldemoura@f5.com }
1801182St.nateldemoura@f5.com
1811306St.nateldemoura@f5.com ret = nxt_clone_credential_map_write(task, mapfile, pid, mapinfo);
1821182St.nateldemoura@f5.com
1831182St.nateldemoura@f5.com nxt_free(mapinfo);
1841182St.nateldemoura@f5.com
1851182St.nateldemoura@f5.com return ret;
1861182St.nateldemoura@f5.com }
1871182St.nateldemoura@f5.com
1881182St.nateldemoura@f5.com
1891182St.nateldemoura@f5.com nxt_int_t
nxt_clone_credential_map(nxt_task_t * task,pid_t pid,nxt_credential_t * app_creds,nxt_clone_t * clone)1901306St.nateldemoura@f5.com nxt_clone_credential_map(nxt_task_t *task, pid_t pid,
1911306St.nateldemoura@f5.com nxt_credential_t *app_creds, nxt_clone_t *clone)
1921182St.nateldemoura@f5.com {
1931182St.nateldemoura@f5.com nxt_int_t ret;
1941306St.nateldemoura@f5.com nxt_int_t default_host_uid;
1951306St.nateldemoura@f5.com nxt_int_t default_host_gid;
1961182St.nateldemoura@f5.com const char *rule;
1971182St.nateldemoura@f5.com nxt_runtime_t *rt;
1981182St.nateldemoura@f5.com
1991182St.nateldemoura@f5.com rt = task->thread->runtime;
2001306St.nateldemoura@f5.com
2011306St.nateldemoura@f5.com if (rt->capabilities.setid) {
2021306St.nateldemoura@f5.com rule = "allow";
2031182St.nateldemoura@f5.com
2041306St.nateldemoura@f5.com /*
2051306St.nateldemoura@f5.com * By default we don't map a privileged user
2061306St.nateldemoura@f5.com */
2071306St.nateldemoura@f5.com default_host_uid = app_creds->uid;
2081306St.nateldemoura@f5.com default_host_gid = app_creds->base_gid;
2091306St.nateldemoura@f5.com } else {
2101306St.nateldemoura@f5.com rule = "deny";
2111182St.nateldemoura@f5.com
2121306St.nateldemoura@f5.com default_host_uid = nxt_euid;
2131306St.nateldemoura@f5.com default_host_gid = nxt_egid;
2141306St.nateldemoura@f5.com }
2151306St.nateldemoura@f5.com
2161306St.nateldemoura@f5.com ret = nxt_clone_credential_map_set(task, "uid_map", pid, app_creds->uid,
2171306St.nateldemoura@f5.com default_host_uid,
2181306St.nateldemoura@f5.com &clone->uidmap);
2191306St.nateldemoura@f5.com
2201182St.nateldemoura@f5.com if (nxt_slow_path(ret != NXT_OK)) {
2211182St.nateldemoura@f5.com return NXT_ERROR;
2221182St.nateldemoura@f5.com }
2231182St.nateldemoura@f5.com
2241306St.nateldemoura@f5.com ret = nxt_clone_credential_setgroups(task, pid, rule);
2251182St.nateldemoura@f5.com if (nxt_slow_path(ret != NXT_OK)) {
2261182St.nateldemoura@f5.com nxt_alert(task, "failed to write /proc/%d/setgroups", pid);
2271182St.nateldemoura@f5.com return NXT_ERROR;
2281182St.nateldemoura@f5.com }
2291182St.nateldemoura@f5.com
2301306St.nateldemoura@f5.com ret = nxt_clone_credential_map_set(task, "gid_map", pid, app_creds->base_gid,
2311306St.nateldemoura@f5.com default_host_gid,
2321306St.nateldemoura@f5.com &clone->gidmap);
2331306St.nateldemoura@f5.com
2341182St.nateldemoura@f5.com if (nxt_slow_path(ret != NXT_OK)) {
2351182St.nateldemoura@f5.com return NXT_ERROR;
2361182St.nateldemoura@f5.com }
2371182St.nateldemoura@f5.com
2381182St.nateldemoura@f5.com return NXT_OK;
2391182St.nateldemoura@f5.com }
2401182St.nateldemoura@f5.com
2411306St.nateldemoura@f5.com
2421306St.nateldemoura@f5.com nxt_int_t
nxt_clone_vldt_credential_uidmap(nxt_task_t * task,nxt_clone_credential_map_t * map,nxt_credential_t * creds)2431306St.nateldemoura@f5.com nxt_clone_vldt_credential_uidmap(nxt_task_t *task,
2441306St.nateldemoura@f5.com nxt_clone_credential_map_t *map, nxt_credential_t *creds)
2451306St.nateldemoura@f5.com {
2461306St.nateldemoura@f5.com nxt_int_t id;
2471306St.nateldemoura@f5.com nxt_uint_t i;
2481306St.nateldemoura@f5.com nxt_runtime_t *rt;
2491306St.nateldemoura@f5.com nxt_clone_map_entry_t m;
2501306St.nateldemoura@f5.com
2511306St.nateldemoura@f5.com if (map->size == 0) {
2521306St.nateldemoura@f5.com return NXT_OK;
2531306St.nateldemoura@f5.com }
2541306St.nateldemoura@f5.com
2551306St.nateldemoura@f5.com rt = task->thread->runtime;
2561306St.nateldemoura@f5.com
2571306St.nateldemoura@f5.com if (!rt->capabilities.setid) {
2581306St.nateldemoura@f5.com if (nxt_slow_path(map->size > 1)) {
2591306St.nateldemoura@f5.com nxt_log(task, NXT_LOG_NOTICE, "\"uidmap\" field has %d entries "
2601306St.nateldemoura@f5.com "but unprivileged unit has a maximum of 1 map.",
2611306St.nateldemoura@f5.com map->size);
2621306St.nateldemoura@f5.com
2631306St.nateldemoura@f5.com return NXT_ERROR;
2641306St.nateldemoura@f5.com }
2651306St.nateldemoura@f5.com
2661306St.nateldemoura@f5.com id = map->map[0].host;
2671306St.nateldemoura@f5.com
2681306St.nateldemoura@f5.com if (nxt_slow_path((nxt_uid_t) id != nxt_euid)) {
2691306St.nateldemoura@f5.com nxt_log(task, NXT_LOG_NOTICE, "\"uidmap\" field has an entry for "
2701306St.nateldemoura@f5.com "host uid %d but unprivileged unit can only map itself "
2711306St.nateldemoura@f5.com "(uid %d) into child namespaces.", id, nxt_euid);
2721306St.nateldemoura@f5.com
2731306St.nateldemoura@f5.com return NXT_ERROR;
2741306St.nateldemoura@f5.com }
2751306St.nateldemoura@f5.com
2761306St.nateldemoura@f5.com return NXT_OK;
2771306St.nateldemoura@f5.com }
2781306St.nateldemoura@f5.com
2791306St.nateldemoura@f5.com for (i = 0; i < map->size; i++) {
2801306St.nateldemoura@f5.com m = map->map[i];
2811306St.nateldemoura@f5.com
2821306St.nateldemoura@f5.com if (creds->uid >= (nxt_uid_t) m.container
2831306St.nateldemoura@f5.com && creds->uid < (nxt_uid_t) (m.container + m.size))
2841306St.nateldemoura@f5.com {
2851306St.nateldemoura@f5.com return NXT_OK;
2861306St.nateldemoura@f5.com }
2871306St.nateldemoura@f5.com }
2881306St.nateldemoura@f5.com
2891306St.nateldemoura@f5.com nxt_log(task, NXT_LOG_NOTICE, "\"uidmap\" field has no \"container\" "
2901306St.nateldemoura@f5.com "entry for user \"%s\" (uid %d)", creds->user, creds->uid);
2911306St.nateldemoura@f5.com
2921306St.nateldemoura@f5.com return NXT_ERROR;
2931306St.nateldemoura@f5.com }
2941306St.nateldemoura@f5.com
2951306St.nateldemoura@f5.com
2961306St.nateldemoura@f5.com nxt_int_t
nxt_clone_vldt_credential_gidmap(nxt_task_t * task,nxt_clone_credential_map_t * map,nxt_credential_t * creds)2971306St.nateldemoura@f5.com nxt_clone_vldt_credential_gidmap(nxt_task_t *task,
2981306St.nateldemoura@f5.com nxt_clone_credential_map_t *map, nxt_credential_t *creds)
2991306St.nateldemoura@f5.com {
3001306St.nateldemoura@f5.com nxt_uint_t base_ok, gid_ok, gids_ok;
3011306St.nateldemoura@f5.com nxt_uint_t i, j;
3021306St.nateldemoura@f5.com nxt_runtime_t *rt;
3031306St.nateldemoura@f5.com nxt_clone_map_entry_t m;
3041306St.nateldemoura@f5.com
3051306St.nateldemoura@f5.com rt = task->thread->runtime;
3061306St.nateldemoura@f5.com
3071306St.nateldemoura@f5.com if (!rt->capabilities.setid) {
3081306St.nateldemoura@f5.com if (creds->ngroups > 0
3091306St.nateldemoura@f5.com && !(creds->ngroups == 1 && creds->gids[0] == creds->base_gid)) {
3101306St.nateldemoura@f5.com nxt_log(task, NXT_LOG_NOTICE,
3111306St.nateldemoura@f5.com "unprivileged unit disallow supplementary groups for "
3121306St.nateldemoura@f5.com "new namespace (user \"%s\" has %d group%s).",
3131306St.nateldemoura@f5.com creds->user, creds->ngroups,
3141306St.nateldemoura@f5.com creds->ngroups > 1 ? "s" : "");
3151306St.nateldemoura@f5.com
3161306St.nateldemoura@f5.com return NXT_ERROR;
3171306St.nateldemoura@f5.com }
3181306St.nateldemoura@f5.com
3191306St.nateldemoura@f5.com if (map->size == 0) {
3201306St.nateldemoura@f5.com return NXT_OK;
3211306St.nateldemoura@f5.com }
3221306St.nateldemoura@f5.com
3231306St.nateldemoura@f5.com if (nxt_slow_path(map->size > 1)) {
3241306St.nateldemoura@f5.com nxt_log(task, NXT_LOG_NOTICE, "\"gidmap\" field has %d entries "
3251306St.nateldemoura@f5.com "but unprivileged unit has a maximum of 1 map.",
3261306St.nateldemoura@f5.com map->size);
3271306St.nateldemoura@f5.com
3281306St.nateldemoura@f5.com return NXT_ERROR;
3291306St.nateldemoura@f5.com }
3301306St.nateldemoura@f5.com
3311306St.nateldemoura@f5.com m = map->map[0];
3321306St.nateldemoura@f5.com
3331306St.nateldemoura@f5.com if (nxt_slow_path((nxt_gid_t) m.host != nxt_egid)) {
3341306St.nateldemoura@f5.com nxt_log(task, NXT_LOG_ERR, "\"gidmap\" field has an entry for "
335*2629Sa.clayton@nginx.com "host gid %L but unprivileged unit can only map itself "
3361306St.nateldemoura@f5.com "(gid %d) into child namespaces.", m.host, nxt_egid);
3371306St.nateldemoura@f5.com
3381306St.nateldemoura@f5.com return NXT_ERROR;
3391306St.nateldemoura@f5.com }
3401306St.nateldemoura@f5.com
3411306St.nateldemoura@f5.com if (nxt_slow_path(m.size > 1)) {
3421306St.nateldemoura@f5.com nxt_log(task, NXT_LOG_ERR, "\"gidmap\" field has an entry with "
343*2629Sa.clayton@nginx.com "\"size\": %L, but for unprivileged unit it must be 1.",
3441306St.nateldemoura@f5.com m.size);
3451306St.nateldemoura@f5.com
3461306St.nateldemoura@f5.com return NXT_ERROR;
3471306St.nateldemoura@f5.com }
3481306St.nateldemoura@f5.com
3491306St.nateldemoura@f5.com if (nxt_slow_path((nxt_gid_t) m.container != creds->base_gid)) {
3501306St.nateldemoura@f5.com nxt_log(task, NXT_LOG_ERR,
3511306St.nateldemoura@f5.com "\"gidmap\" field has no \"container\" entry for gid %d.",
3521306St.nateldemoura@f5.com creds->base_gid);
3531306St.nateldemoura@f5.com
3541306St.nateldemoura@f5.com return NXT_ERROR;
3551306St.nateldemoura@f5.com }
3561306St.nateldemoura@f5.com
3571306St.nateldemoura@f5.com return NXT_OK;
3581306St.nateldemoura@f5.com }
3591306St.nateldemoura@f5.com
3601306St.nateldemoura@f5.com if (map->size == 0) {
3611306St.nateldemoura@f5.com if (creds->ngroups > 0
3621306St.nateldemoura@f5.com && !(creds->ngroups == 1 && creds->gids[0] == creds->base_gid))
3631306St.nateldemoura@f5.com {
3641306St.nateldemoura@f5.com nxt_log(task, NXT_LOG_ERR, "\"gidmap\" field has no entries "
3651306St.nateldemoura@f5.com "but user \"%s\" has %d suplementary group%s.",
3661306St.nateldemoura@f5.com creds->user, creds->ngroups,
3671306St.nateldemoura@f5.com creds->ngroups > 1 ? "s" : "");
3681306St.nateldemoura@f5.com
3691306St.nateldemoura@f5.com return NXT_ERROR;
3701306St.nateldemoura@f5.com }
3711306St.nateldemoura@f5.com
3721306St.nateldemoura@f5.com return NXT_OK;
3732078Salx.manpages@gmail.com }
3741306St.nateldemoura@f5.com
3751306St.nateldemoura@f5.com base_ok = 0;
3761306St.nateldemoura@f5.com gids_ok = 0;
3771306St.nateldemoura@f5.com
3781306St.nateldemoura@f5.com for (i = 0; i < creds->ngroups; i++) {
3791306St.nateldemoura@f5.com gid_ok = 0;
3801306St.nateldemoura@f5.com
3811306St.nateldemoura@f5.com for (j = 0; j < map->size; j++) {
3821306St.nateldemoura@f5.com m = map->map[j];
3831306St.nateldemoura@f5.com
3841306St.nateldemoura@f5.com if (!base_ok && creds->base_gid >= (nxt_gid_t) m.container
3852617Szelenkov@nginx.com && creds->base_gid < (nxt_gid_t) (m.container + m.size))
3861306St.nateldemoura@f5.com {
3871306St.nateldemoura@f5.com base_ok = 1;
3881306St.nateldemoura@f5.com }
3891306St.nateldemoura@f5.com
3901306St.nateldemoura@f5.com if (creds->gids[i] >= (nxt_gid_t) m.container
3912617Szelenkov@nginx.com && creds->gids[i] < (nxt_gid_t) (m.container + m.size))
3921306St.nateldemoura@f5.com {
3931306St.nateldemoura@f5.com gid_ok = 1;
3941306St.nateldemoura@f5.com break;
3951306St.nateldemoura@f5.com }
3961306St.nateldemoura@f5.com }
3971306St.nateldemoura@f5.com
3981306St.nateldemoura@f5.com if (nxt_fast_path(gid_ok)) {
3991306St.nateldemoura@f5.com gids_ok++;
4001306St.nateldemoura@f5.com }
4011306St.nateldemoura@f5.com }
4021306St.nateldemoura@f5.com
4031306St.nateldemoura@f5.com if (!base_ok) {
4041306St.nateldemoura@f5.com for (i = 0; i < map->size; i++) {
4051306St.nateldemoura@f5.com m = map->map[i];
4061306St.nateldemoura@f5.com
4071306St.nateldemoura@f5.com if (creds->base_gid >= (nxt_gid_t) m.container
4082617Szelenkov@nginx.com && creds->base_gid < (nxt_gid_t) (m.container + m.size))
4091306St.nateldemoura@f5.com {
4101306St.nateldemoura@f5.com base_ok = 1;
4111306St.nateldemoura@f5.com break;
4121306St.nateldemoura@f5.com }
4131306St.nateldemoura@f5.com }
4141306St.nateldemoura@f5.com }
4151306St.nateldemoura@f5.com
4161306St.nateldemoura@f5.com if (nxt_slow_path(!base_ok)) {
4171306St.nateldemoura@f5.com nxt_log(task, NXT_LOG_ERR, "\"gidmap\" field has no \"container\" "
4181306St.nateldemoura@f5.com "entry for gid %d.", creds->base_gid);
4191306St.nateldemoura@f5.com
4201306St.nateldemoura@f5.com return NXT_ERROR;
4211306St.nateldemoura@f5.com }
4221306St.nateldemoura@f5.com
4231306St.nateldemoura@f5.com if (nxt_slow_path(gids_ok < creds->ngroups)) {
4241306St.nateldemoura@f5.com nxt_log(task, NXT_LOG_ERR, "\"gidmap\" field has missing "
4251306St.nateldemoura@f5.com "suplementary gid mappings (found %d out of %d).", gids_ok,
4261306St.nateldemoura@f5.com creds->ngroups);
4271306St.nateldemoura@f5.com
4281306St.nateldemoura@f5.com return NXT_ERROR;
4291306St.nateldemoura@f5.com }
4301306St.nateldemoura@f5.com
4311306St.nateldemoura@f5.com return NXT_OK;
4321306St.nateldemoura@f5.com }
4331306St.nateldemoura@f5.com
4341182St.nateldemoura@f5.com #endif
435