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 #if (NXT_HAVE_CLONE) 121182St.nateldemoura@f5.com 131182St.nateldemoura@f5.com pid_t 141182St.nateldemoura@f5.com nxt_clone(nxt_int_t flags) 151182St.nateldemoura@f5.com { 161182St.nateldemoura@f5.com #if defined(__s390x__) || defined(__s390__) || defined(__CRIS__) 171182St.nateldemoura@f5.com return syscall(__NR_clone, NULL, flags); 181182St.nateldemoura@f5.com #else 191182St.nateldemoura@f5.com return syscall(__NR_clone, flags, NULL); 201182St.nateldemoura@f5.com #endif 211182St.nateldemoura@f5.com } 221182St.nateldemoura@f5.com 231182St.nateldemoura@f5.com #endif 241182St.nateldemoura@f5.com 251182St.nateldemoura@f5.com 261182St.nateldemoura@f5.com #if (NXT_HAVE_CLONE_NEWUSER) 271182St.nateldemoura@f5.com 281306St.nateldemoura@f5.com nxt_int_t nxt_clone_credential_setgroups(nxt_task_t *task, pid_t child_pid, 291182St.nateldemoura@f5.com const char *str); 301306St.nateldemoura@f5.com nxt_int_t nxt_clone_credential_map_set(nxt_task_t *task, const char* mapfile, 311306St.nateldemoura@f5.com pid_t pid, nxt_int_t default_container, nxt_int_t default_host, 321306St.nateldemoura@f5.com nxt_clone_credential_map_t *map); 331306St.nateldemoura@f5.com nxt_int_t nxt_clone_credential_map_write(nxt_task_t *task, const char *mapfile, 341182St.nateldemoura@f5.com pid_t pid, u_char *mapinfo); 351182St.nateldemoura@f5.com 361182St.nateldemoura@f5.com 371182St.nateldemoura@f5.com nxt_int_t 381306St.nateldemoura@f5.com nxt_clone_credential_setgroups(nxt_task_t *task, pid_t child_pid, 391306St.nateldemoura@f5.com const char *str) 401182St.nateldemoura@f5.com { 411182St.nateldemoura@f5.com int fd, n; 421182St.nateldemoura@f5.com u_char *p, *end; 431182St.nateldemoura@f5.com u_char path[PATH_MAX]; 441182St.nateldemoura@f5.com 451182St.nateldemoura@f5.com end = path + PATH_MAX; 461182St.nateldemoura@f5.com p = nxt_sprintf(path, end, "/proc/%d/setgroups", child_pid); 471182St.nateldemoura@f5.com *p = '\0'; 481182St.nateldemoura@f5.com 491182St.nateldemoura@f5.com if (nxt_slow_path(p == end)) { 501182St.nateldemoura@f5.com nxt_alert(task, "error write past the buffer: %s", path); 511182St.nateldemoura@f5.com return NXT_ERROR; 521182St.nateldemoura@f5.com } 531182St.nateldemoura@f5.com 541182St.nateldemoura@f5.com fd = open((char *)path, O_RDWR); 551182St.nateldemoura@f5.com 561182St.nateldemoura@f5.com if (fd == -1) { 571182St.nateldemoura@f5.com /* 581182St.nateldemoura@f5.com * If the /proc/pid/setgroups doesn't exists, we are 591182St.nateldemoura@f5.com * safe to set uid/gid maps. But if the error is anything 601182St.nateldemoura@f5.com * other than ENOENT, then we should abort and let user know. 611182St.nateldemoura@f5.com */ 621182St.nateldemoura@f5.com 631182St.nateldemoura@f5.com if (errno != ENOENT) { 641182St.nateldemoura@f5.com nxt_alert(task, "open(%s): %E", path, nxt_errno); 651182St.nateldemoura@f5.com return NXT_ERROR; 661182St.nateldemoura@f5.com } 671182St.nateldemoura@f5.com 681182St.nateldemoura@f5.com return NXT_OK; 691182St.nateldemoura@f5.com } 701182St.nateldemoura@f5.com 711182St.nateldemoura@f5.com n = write(fd, str, strlen(str)); 721182St.nateldemoura@f5.com close(fd); 731182St.nateldemoura@f5.com 741182St.nateldemoura@f5.com if (nxt_slow_path(n == -1)) { 751182St.nateldemoura@f5.com nxt_alert(task, "write(%s): %E", path, nxt_errno); 761182St.nateldemoura@f5.com return NXT_ERROR; 771182St.nateldemoura@f5.com } 781182St.nateldemoura@f5.com 791182St.nateldemoura@f5.com return NXT_OK; 801182St.nateldemoura@f5.com } 811182St.nateldemoura@f5.com 821182St.nateldemoura@f5.com 831182St.nateldemoura@f5.com nxt_int_t 841306St.nateldemoura@f5.com nxt_clone_credential_map_write(nxt_task_t *task, const char *mapfile, 851306St.nateldemoura@f5.com pid_t pid, u_char *mapinfo) 861182St.nateldemoura@f5.com { 871182St.nateldemoura@f5.com int len, mapfd; 881182St.nateldemoura@f5.com u_char *p, *end; 891182St.nateldemoura@f5.com ssize_t n; 901182St.nateldemoura@f5.com u_char buf[256]; 911182St.nateldemoura@f5.com 921182St.nateldemoura@f5.com end = buf + sizeof(buf); 931182St.nateldemoura@f5.com 941182St.nateldemoura@f5.com p = nxt_sprintf(buf, end, "/proc/%d/%s", pid, mapfile); 951182St.nateldemoura@f5.com if (nxt_slow_path(p == end)) { 961182St.nateldemoura@f5.com nxt_alert(task, "writing past the buffer"); 971182St.nateldemoura@f5.com return NXT_ERROR; 981182St.nateldemoura@f5.com } 991182St.nateldemoura@f5.com 1001182St.nateldemoura@f5.com *p = '\0'; 1011182St.nateldemoura@f5.com 1021182St.nateldemoura@f5.com mapfd = open((char*)buf, O_RDWR); 1031182St.nateldemoura@f5.com if (nxt_slow_path(mapfd == -1)) { 1041182St.nateldemoura@f5.com nxt_alert(task, "failed to open proc map (%s) %E", buf, nxt_errno); 1051182St.nateldemoura@f5.com return NXT_ERROR; 1061182St.nateldemoura@f5.com } 1071182St.nateldemoura@f5.com 1081182St.nateldemoura@f5.com len = nxt_strlen(mapinfo); 1091182St.nateldemoura@f5.com 1101182St.nateldemoura@f5.com n = write(mapfd, (char *)mapinfo, len); 1111182St.nateldemoura@f5.com if (nxt_slow_path(n != len)) { 1121182St.nateldemoura@f5.com 1131182St.nateldemoura@f5.com if (n == -1 && nxt_errno == EINVAL) { 1141182St.nateldemoura@f5.com nxt_alert(task, "failed to write %s: Check kernel maximum " \ 1151182St.nateldemoura@f5.com "allowed lines %E", buf, nxt_errno); 1161182St.nateldemoura@f5.com 1171182St.nateldemoura@f5.com } else { 1181182St.nateldemoura@f5.com nxt_alert(task, "failed to write proc map (%s) %E", buf, 1191182St.nateldemoura@f5.com nxt_errno); 1201182St.nateldemoura@f5.com } 1211182St.nateldemoura@f5.com 1221201St.nateldemoura@f5.com close(mapfd); 1231201St.nateldemoura@f5.com 1241182St.nateldemoura@f5.com return NXT_ERROR; 1251182St.nateldemoura@f5.com } 1261182St.nateldemoura@f5.com 1271201St.nateldemoura@f5.com close(mapfd); 1281201St.nateldemoura@f5.com 1291182St.nateldemoura@f5.com return NXT_OK; 1301182St.nateldemoura@f5.com } 1311182St.nateldemoura@f5.com 1321182St.nateldemoura@f5.com 1331182St.nateldemoura@f5.com nxt_int_t 1341306St.nateldemoura@f5.com nxt_clone_credential_map_set(nxt_task_t *task, const char* mapfile, pid_t pid, 1351306St.nateldemoura@f5.com nxt_int_t default_container, nxt_int_t default_host, 1361306St.nateldemoura@f5.com nxt_clone_credential_map_t *map) 1371182St.nateldemoura@f5.com { 1381306St.nateldemoura@f5.com u_char *p, *end, *mapinfo; 1391306St.nateldemoura@f5.com nxt_int_t ret, len; 1401306St.nateldemoura@f5.com nxt_uint_t i; 1411182St.nateldemoura@f5.com 1421182St.nateldemoura@f5.com /* 1431182St.nateldemoura@f5.com * uid_map one-entry size: 1441182St.nateldemoura@f5.com * alloc space for 3 numbers (32bit) plus 2 spaces and \n. 1451182St.nateldemoura@f5.com */ 1461182St.nateldemoura@f5.com len = sizeof(u_char) * (10 + 10 + 10 + 2 + 1); 1471182St.nateldemoura@f5.com 1481306St.nateldemoura@f5.com if (map->size > 0) { 1491306St.nateldemoura@f5.com len = len * map->size + 1; 1501182St.nateldemoura@f5.com 1511182St.nateldemoura@f5.com mapinfo = nxt_malloc(len); 1521182St.nateldemoura@f5.com if (nxt_slow_path(mapinfo == NULL)) { 1531182St.nateldemoura@f5.com return NXT_ERROR; 1541182St.nateldemoura@f5.com } 1551182St.nateldemoura@f5.com 1561182St.nateldemoura@f5.com p = mapinfo; 1571182St.nateldemoura@f5.com end = mapinfo + len; 1581182St.nateldemoura@f5.com 1591306St.nateldemoura@f5.com for (i = 0; i < map->size; i++) { 1601306St.nateldemoura@f5.com p = nxt_sprintf(p, end, "%d %d %d", map->map[i].container, 1611306St.nateldemoura@f5.com map->map[i].host, map->map[i].size); 1621182St.nateldemoura@f5.com 1631182St.nateldemoura@f5.com if (nxt_slow_path(p == end)) { 1641306St.nateldemoura@f5.com nxt_alert(task, "write past the mapinfo buffer"); 1651182St.nateldemoura@f5.com nxt_free(mapinfo); 1661182St.nateldemoura@f5.com return NXT_ERROR; 1671182St.nateldemoura@f5.com } 1681182St.nateldemoura@f5.com 1691306St.nateldemoura@f5.com if (i+1 < map->size) { 1701182St.nateldemoura@f5.com *p++ = '\n'; 1711182St.nateldemoura@f5.com 1721182St.nateldemoura@f5.com } else { 1731182St.nateldemoura@f5.com *p = '\0'; 1741182St.nateldemoura@f5.com } 1751182St.nateldemoura@f5.com } 1761182St.nateldemoura@f5.com 1771182St.nateldemoura@f5.com } else { 1781182St.nateldemoura@f5.com mapinfo = nxt_malloc(len); 1791182St.nateldemoura@f5.com if (nxt_slow_path(mapinfo == NULL)) { 1801182St.nateldemoura@f5.com return NXT_ERROR; 1811182St.nateldemoura@f5.com } 1821182St.nateldemoura@f5.com 1831182St.nateldemoura@f5.com end = mapinfo + len; 1841306St.nateldemoura@f5.com p = nxt_sprintf(mapinfo, end, "%d %d 1", 1851306St.nateldemoura@f5.com default_container, default_host); 1861182St.nateldemoura@f5.com *p = '\0'; 1871182St.nateldemoura@f5.com 1881182St.nateldemoura@f5.com if (nxt_slow_path(p == end)) { 1891306St.nateldemoura@f5.com nxt_alert(task, "write past mapinfo buffer"); 1901182St.nateldemoura@f5.com nxt_free(mapinfo); 1911182St.nateldemoura@f5.com return NXT_ERROR; 1921182St.nateldemoura@f5.com } 1931182St.nateldemoura@f5.com } 1941182St.nateldemoura@f5.com 1951306St.nateldemoura@f5.com ret = nxt_clone_credential_map_write(task, mapfile, pid, mapinfo); 1961182St.nateldemoura@f5.com 1971182St.nateldemoura@f5.com nxt_free(mapinfo); 1981182St.nateldemoura@f5.com 1991182St.nateldemoura@f5.com return ret; 2001182St.nateldemoura@f5.com } 2011182St.nateldemoura@f5.com 2021182St.nateldemoura@f5.com 2031182St.nateldemoura@f5.com nxt_int_t 2041306St.nateldemoura@f5.com nxt_clone_credential_map(nxt_task_t *task, pid_t pid, 2051306St.nateldemoura@f5.com nxt_credential_t *app_creds, nxt_clone_t *clone) 2061182St.nateldemoura@f5.com { 2071182St.nateldemoura@f5.com nxt_int_t ret; 2081306St.nateldemoura@f5.com nxt_int_t default_host_uid; 2091306St.nateldemoura@f5.com nxt_int_t default_host_gid; 2101182St.nateldemoura@f5.com const char *rule; 2111182St.nateldemoura@f5.com nxt_runtime_t *rt; 2121182St.nateldemoura@f5.com 2131182St.nateldemoura@f5.com rt = task->thread->runtime; 2141306St.nateldemoura@f5.com 2151306St.nateldemoura@f5.com if (rt->capabilities.setid) { 2161306St.nateldemoura@f5.com rule = "allow"; 2171182St.nateldemoura@f5.com 2181306St.nateldemoura@f5.com /* 2191306St.nateldemoura@f5.com * By default we don't map a privileged user 2201306St.nateldemoura@f5.com */ 2211306St.nateldemoura@f5.com default_host_uid = app_creds->uid; 2221306St.nateldemoura@f5.com default_host_gid = app_creds->base_gid; 2231306St.nateldemoura@f5.com } else { 2241306St.nateldemoura@f5.com rule = "deny"; 2251182St.nateldemoura@f5.com 2261306St.nateldemoura@f5.com default_host_uid = nxt_euid; 2271306St.nateldemoura@f5.com default_host_gid = nxt_egid; 2281306St.nateldemoura@f5.com } 2291306St.nateldemoura@f5.com 2301306St.nateldemoura@f5.com ret = nxt_clone_credential_map_set(task, "uid_map", pid, app_creds->uid, 2311306St.nateldemoura@f5.com default_host_uid, 2321306St.nateldemoura@f5.com &clone->uidmap); 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 2381306St.nateldemoura@f5.com ret = nxt_clone_credential_setgroups(task, pid, rule); 2391182St.nateldemoura@f5.com if (nxt_slow_path(ret != NXT_OK)) { 2401182St.nateldemoura@f5.com nxt_alert(task, "failed to write /proc/%d/setgroups", pid); 2411182St.nateldemoura@f5.com return NXT_ERROR; 2421182St.nateldemoura@f5.com } 2431182St.nateldemoura@f5.com 2441306St.nateldemoura@f5.com ret = nxt_clone_credential_map_set(task, "gid_map", pid, app_creds->base_gid, 2451306St.nateldemoura@f5.com default_host_gid, 2461306St.nateldemoura@f5.com &clone->gidmap); 2471306St.nateldemoura@f5.com 2481182St.nateldemoura@f5.com if (nxt_slow_path(ret != NXT_OK)) { 2491182St.nateldemoura@f5.com return NXT_ERROR; 2501182St.nateldemoura@f5.com } 2511182St.nateldemoura@f5.com 2521182St.nateldemoura@f5.com return NXT_OK; 2531182St.nateldemoura@f5.com } 2541182St.nateldemoura@f5.com 2551306St.nateldemoura@f5.com 2561306St.nateldemoura@f5.com nxt_int_t 2571306St.nateldemoura@f5.com nxt_clone_vldt_credential_uidmap(nxt_task_t *task, 2581306St.nateldemoura@f5.com nxt_clone_credential_map_t *map, nxt_credential_t *creds) 2591306St.nateldemoura@f5.com { 2601306St.nateldemoura@f5.com nxt_int_t id; 2611306St.nateldemoura@f5.com nxt_uint_t i; 2621306St.nateldemoura@f5.com nxt_runtime_t *rt; 2631306St.nateldemoura@f5.com nxt_clone_map_entry_t m; 2641306St.nateldemoura@f5.com 2651306St.nateldemoura@f5.com if (map->size == 0) { 2661306St.nateldemoura@f5.com return NXT_OK; 2671306St.nateldemoura@f5.com } 2681306St.nateldemoura@f5.com 2691306St.nateldemoura@f5.com rt = task->thread->runtime; 2701306St.nateldemoura@f5.com 2711306St.nateldemoura@f5.com if (!rt->capabilities.setid) { 2721306St.nateldemoura@f5.com if (nxt_slow_path(map->size > 1)) { 2731306St.nateldemoura@f5.com nxt_log(task, NXT_LOG_NOTICE, "\"uidmap\" field has %d entries " 2741306St.nateldemoura@f5.com "but unprivileged unit has a maximum of 1 map.", 2751306St.nateldemoura@f5.com map->size); 2761306St.nateldemoura@f5.com 2771306St.nateldemoura@f5.com return NXT_ERROR; 2781306St.nateldemoura@f5.com } 2791306St.nateldemoura@f5.com 2801306St.nateldemoura@f5.com id = map->map[0].host; 2811306St.nateldemoura@f5.com 2821306St.nateldemoura@f5.com if (nxt_slow_path((nxt_uid_t) id != nxt_euid)) { 2831306St.nateldemoura@f5.com nxt_log(task, NXT_LOG_NOTICE, "\"uidmap\" field has an entry for " 2841306St.nateldemoura@f5.com "host uid %d but unprivileged unit can only map itself " 2851306St.nateldemoura@f5.com "(uid %d) into child namespaces.", id, nxt_euid); 2861306St.nateldemoura@f5.com 2871306St.nateldemoura@f5.com return NXT_ERROR; 2881306St.nateldemoura@f5.com } 2891306St.nateldemoura@f5.com 2901306St.nateldemoura@f5.com return NXT_OK; 2911306St.nateldemoura@f5.com } 2921306St.nateldemoura@f5.com 2931306St.nateldemoura@f5.com for (i = 0; i < map->size; i++) { 2941306St.nateldemoura@f5.com m = map->map[i]; 2951306St.nateldemoura@f5.com 2961306St.nateldemoura@f5.com if (creds->uid >= (nxt_uid_t) m.container 2971306St.nateldemoura@f5.com && creds->uid < (nxt_uid_t) (m.container + m.size)) 2981306St.nateldemoura@f5.com { 2991306St.nateldemoura@f5.com return NXT_OK; 3001306St.nateldemoura@f5.com } 3011306St.nateldemoura@f5.com } 3021306St.nateldemoura@f5.com 3031306St.nateldemoura@f5.com nxt_log(task, NXT_LOG_NOTICE, "\"uidmap\" field has no \"container\" " 3041306St.nateldemoura@f5.com "entry for user \"%s\" (uid %d)", creds->user, creds->uid); 3051306St.nateldemoura@f5.com 3061306St.nateldemoura@f5.com return NXT_ERROR; 3071306St.nateldemoura@f5.com } 3081306St.nateldemoura@f5.com 3091306St.nateldemoura@f5.com 3101306St.nateldemoura@f5.com nxt_int_t 3111306St.nateldemoura@f5.com nxt_clone_vldt_credential_gidmap(nxt_task_t *task, 3121306St.nateldemoura@f5.com nxt_clone_credential_map_t *map, nxt_credential_t *creds) 3131306St.nateldemoura@f5.com { 3141306St.nateldemoura@f5.com nxt_uint_t base_ok, gid_ok, gids_ok; 3151306St.nateldemoura@f5.com nxt_uint_t i, j; 3161306St.nateldemoura@f5.com nxt_runtime_t *rt; 3171306St.nateldemoura@f5.com nxt_clone_map_entry_t m; 3181306St.nateldemoura@f5.com 3191306St.nateldemoura@f5.com rt = task->thread->runtime; 3201306St.nateldemoura@f5.com 3211306St.nateldemoura@f5.com if (!rt->capabilities.setid) { 3221306St.nateldemoura@f5.com if (creds->ngroups > 0 3231306St.nateldemoura@f5.com && !(creds->ngroups == 1 && creds->gids[0] == creds->base_gid)) { 3241306St.nateldemoura@f5.com nxt_log(task, NXT_LOG_NOTICE, 3251306St.nateldemoura@f5.com "unprivileged unit disallow supplementary groups for " 3261306St.nateldemoura@f5.com "new namespace (user \"%s\" has %d group%s).", 3271306St.nateldemoura@f5.com creds->user, creds->ngroups, 3281306St.nateldemoura@f5.com creds->ngroups > 1 ? "s" : ""); 3291306St.nateldemoura@f5.com 3301306St.nateldemoura@f5.com return NXT_ERROR; 3311306St.nateldemoura@f5.com } 3321306St.nateldemoura@f5.com 3331306St.nateldemoura@f5.com if (map->size == 0) { 3341306St.nateldemoura@f5.com return NXT_OK; 3351306St.nateldemoura@f5.com } 3361306St.nateldemoura@f5.com 3371306St.nateldemoura@f5.com if (nxt_slow_path(map->size > 1)) { 3381306St.nateldemoura@f5.com nxt_log(task, NXT_LOG_NOTICE, "\"gidmap\" field has %d entries " 3391306St.nateldemoura@f5.com "but unprivileged unit has a maximum of 1 map.", 3401306St.nateldemoura@f5.com map->size); 3411306St.nateldemoura@f5.com 3421306St.nateldemoura@f5.com return NXT_ERROR; 3431306St.nateldemoura@f5.com } 3441306St.nateldemoura@f5.com 3451306St.nateldemoura@f5.com m = map->map[0]; 3461306St.nateldemoura@f5.com 3471306St.nateldemoura@f5.com if (nxt_slow_path((nxt_gid_t) m.host != nxt_egid)) { 3481306St.nateldemoura@f5.com nxt_log(task, NXT_LOG_ERR, "\"gidmap\" field has an entry for " 3491306St.nateldemoura@f5.com "host gid %d but unprivileged unit can only map itself " 3501306St.nateldemoura@f5.com "(gid %d) into child namespaces.", m.host, nxt_egid); 3511306St.nateldemoura@f5.com 3521306St.nateldemoura@f5.com return NXT_ERROR; 3531306St.nateldemoura@f5.com } 3541306St.nateldemoura@f5.com 3551306St.nateldemoura@f5.com if (nxt_slow_path(m.size > 1)) { 3561306St.nateldemoura@f5.com nxt_log(task, NXT_LOG_ERR, "\"gidmap\" field has an entry with " 3571306St.nateldemoura@f5.com "\"size\": %d, but for unprivileged unit it must be 1.", 3581306St.nateldemoura@f5.com m.size); 3591306St.nateldemoura@f5.com 3601306St.nateldemoura@f5.com return NXT_ERROR; 3611306St.nateldemoura@f5.com } 3621306St.nateldemoura@f5.com 3631306St.nateldemoura@f5.com if (nxt_slow_path((nxt_gid_t) m.container != creds->base_gid)) { 3641306St.nateldemoura@f5.com nxt_log(task, NXT_LOG_ERR, 3651306St.nateldemoura@f5.com "\"gidmap\" field has no \"container\" entry for gid %d.", 3661306St.nateldemoura@f5.com creds->base_gid); 3671306St.nateldemoura@f5.com 3681306St.nateldemoura@f5.com return NXT_ERROR; 3691306St.nateldemoura@f5.com } 3701306St.nateldemoura@f5.com 3711306St.nateldemoura@f5.com return NXT_OK; 3721306St.nateldemoura@f5.com } 3731306St.nateldemoura@f5.com 3741306St.nateldemoura@f5.com if (map->size == 0) { 3751306St.nateldemoura@f5.com if (creds->ngroups > 0 3761306St.nateldemoura@f5.com && !(creds->ngroups == 1 && creds->gids[0] == creds->base_gid)) 3771306St.nateldemoura@f5.com { 3781306St.nateldemoura@f5.com nxt_log(task, NXT_LOG_ERR, "\"gidmap\" field has no entries " 3791306St.nateldemoura@f5.com "but user \"%s\" has %d suplementary group%s.", 3801306St.nateldemoura@f5.com creds->user, creds->ngroups, 3811306St.nateldemoura@f5.com creds->ngroups > 1 ? "s" : ""); 3821306St.nateldemoura@f5.com 3831306St.nateldemoura@f5.com return NXT_ERROR; 3841306St.nateldemoura@f5.com } 3851306St.nateldemoura@f5.com 3861306St.nateldemoura@f5.com return NXT_OK; 387*2078Salx.manpages@gmail.com } 3881306St.nateldemoura@f5.com 3891306St.nateldemoura@f5.com base_ok = 0; 3901306St.nateldemoura@f5.com gids_ok = 0; 3911306St.nateldemoura@f5.com 3921306St.nateldemoura@f5.com for (i = 0; i < creds->ngroups; i++) { 3931306St.nateldemoura@f5.com gid_ok = 0; 3941306St.nateldemoura@f5.com 3951306St.nateldemoura@f5.com for (j = 0; j < map->size; j++) { 3961306St.nateldemoura@f5.com m = map->map[j]; 3971306St.nateldemoura@f5.com 3981306St.nateldemoura@f5.com if (!base_ok && creds->base_gid >= (nxt_gid_t) m.container 3991306St.nateldemoura@f5.com && creds->base_gid < (nxt_gid_t) (m.container+m.size)) 4001306St.nateldemoura@f5.com { 4011306St.nateldemoura@f5.com base_ok = 1; 4021306St.nateldemoura@f5.com } 4031306St.nateldemoura@f5.com 4041306St.nateldemoura@f5.com if (creds->gids[i] >= (nxt_gid_t) m.container 4051306St.nateldemoura@f5.com && creds->gids[i] < (nxt_gid_t) (m.container+m.size)) 4061306St.nateldemoura@f5.com { 4071306St.nateldemoura@f5.com gid_ok = 1; 4081306St.nateldemoura@f5.com break; 4091306St.nateldemoura@f5.com } 4101306St.nateldemoura@f5.com } 4111306St.nateldemoura@f5.com 4121306St.nateldemoura@f5.com if (nxt_fast_path(gid_ok)) { 4131306St.nateldemoura@f5.com gids_ok++; 4141306St.nateldemoura@f5.com } 4151306St.nateldemoura@f5.com } 4161306St.nateldemoura@f5.com 4171306St.nateldemoura@f5.com if (!base_ok) { 4181306St.nateldemoura@f5.com for (i = 0; i < map->size; i++) { 4191306St.nateldemoura@f5.com m = map->map[i]; 4201306St.nateldemoura@f5.com 4211306St.nateldemoura@f5.com if (creds->base_gid >= (nxt_gid_t) m.container 4221306St.nateldemoura@f5.com && creds->base_gid < (nxt_gid_t) (m.container+m.size)) 4231306St.nateldemoura@f5.com { 4241306St.nateldemoura@f5.com base_ok = 1; 4251306St.nateldemoura@f5.com break; 4261306St.nateldemoura@f5.com } 4271306St.nateldemoura@f5.com } 4281306St.nateldemoura@f5.com } 4291306St.nateldemoura@f5.com 4301306St.nateldemoura@f5.com if (nxt_slow_path(!base_ok)) { 4311306St.nateldemoura@f5.com nxt_log(task, NXT_LOG_ERR, "\"gidmap\" field has no \"container\" " 4321306St.nateldemoura@f5.com "entry for gid %d.", creds->base_gid); 4331306St.nateldemoura@f5.com 4341306St.nateldemoura@f5.com return NXT_ERROR; 4351306St.nateldemoura@f5.com } 4361306St.nateldemoura@f5.com 4371306St.nateldemoura@f5.com if (nxt_slow_path(gids_ok < creds->ngroups)) { 4381306St.nateldemoura@f5.com nxt_log(task, NXT_LOG_ERR, "\"gidmap\" field has missing " 4391306St.nateldemoura@f5.com "suplementary gid mappings (found %d out of %d).", gids_ok, 4401306St.nateldemoura@f5.com creds->ngroups); 4411306St.nateldemoura@f5.com 4421306St.nateldemoura@f5.com return NXT_ERROR; 4431306St.nateldemoura@f5.com } 4441306St.nateldemoura@f5.com 4451306St.nateldemoura@f5.com return NXT_OK; 4461306St.nateldemoura@f5.com } 4471306St.nateldemoura@f5.com 4481182St.nateldemoura@f5.com #endif 449