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 28*1306St.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); 30*1306St.nateldemoura@f5.com nxt_int_t nxt_clone_credential_map_set(nxt_task_t *task, const char* mapfile, 31*1306St.nateldemoura@f5.com pid_t pid, nxt_int_t default_container, nxt_int_t default_host, 32*1306St.nateldemoura@f5.com nxt_clone_credential_map_t *map); 33*1306St.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 38*1306St.nateldemoura@f5.com nxt_clone_credential_setgroups(nxt_task_t *task, pid_t child_pid, 39*1306St.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 84*1306St.nateldemoura@f5.com nxt_clone_credential_map_write(nxt_task_t *task, const char *mapfile, 85*1306St.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 134*1306St.nateldemoura@f5.com nxt_clone_credential_map_set(nxt_task_t *task, const char* mapfile, pid_t pid, 135*1306St.nateldemoura@f5.com nxt_int_t default_container, nxt_int_t default_host, 136*1306St.nateldemoura@f5.com nxt_clone_credential_map_t *map) 1371182St.nateldemoura@f5.com { 138*1306St.nateldemoura@f5.com u_char *p, *end, *mapinfo; 139*1306St.nateldemoura@f5.com nxt_int_t ret, len; 140*1306St.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 148*1306St.nateldemoura@f5.com if (map->size > 0) { 149*1306St.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 159*1306St.nateldemoura@f5.com for (i = 0; i < map->size; i++) { 160*1306St.nateldemoura@f5.com p = nxt_sprintf(p, end, "%d %d %d", map->map[i].container, 161*1306St.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)) { 164*1306St.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 169*1306St.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; 184*1306St.nateldemoura@f5.com p = nxt_sprintf(mapinfo, end, "%d %d 1", 185*1306St.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)) { 189*1306St.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 195*1306St.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 204*1306St.nateldemoura@f5.com nxt_clone_credential_map(nxt_task_t *task, pid_t pid, 205*1306St.nateldemoura@f5.com nxt_credential_t *app_creds, nxt_clone_t *clone) 2061182St.nateldemoura@f5.com { 2071182St.nateldemoura@f5.com nxt_int_t ret; 208*1306St.nateldemoura@f5.com nxt_int_t default_host_uid; 209*1306St.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; 214*1306St.nateldemoura@f5.com 215*1306St.nateldemoura@f5.com if (rt->capabilities.setid) { 216*1306St.nateldemoura@f5.com rule = "allow"; 2171182St.nateldemoura@f5.com 218*1306St.nateldemoura@f5.com /* 219*1306St.nateldemoura@f5.com * By default we don't map a privileged user 220*1306St.nateldemoura@f5.com */ 221*1306St.nateldemoura@f5.com default_host_uid = app_creds->uid; 222*1306St.nateldemoura@f5.com default_host_gid = app_creds->base_gid; 223*1306St.nateldemoura@f5.com } else { 224*1306St.nateldemoura@f5.com rule = "deny"; 2251182St.nateldemoura@f5.com 226*1306St.nateldemoura@f5.com default_host_uid = nxt_euid; 227*1306St.nateldemoura@f5.com default_host_gid = nxt_egid; 228*1306St.nateldemoura@f5.com } 229*1306St.nateldemoura@f5.com 230*1306St.nateldemoura@f5.com ret = nxt_clone_credential_map_set(task, "uid_map", pid, app_creds->uid, 231*1306St.nateldemoura@f5.com default_host_uid, 232*1306St.nateldemoura@f5.com &clone->uidmap); 233*1306St.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 238*1306St.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 244*1306St.nateldemoura@f5.com ret = nxt_clone_credential_map_set(task, "gid_map", pid, app_creds->base_gid, 245*1306St.nateldemoura@f5.com default_host_gid, 246*1306St.nateldemoura@f5.com &clone->gidmap); 247*1306St.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 255*1306St.nateldemoura@f5.com 256*1306St.nateldemoura@f5.com nxt_int_t 257*1306St.nateldemoura@f5.com nxt_clone_vldt_credential_uidmap(nxt_task_t *task, 258*1306St.nateldemoura@f5.com nxt_clone_credential_map_t *map, nxt_credential_t *creds) 259*1306St.nateldemoura@f5.com { 260*1306St.nateldemoura@f5.com nxt_int_t id; 261*1306St.nateldemoura@f5.com nxt_uint_t i; 262*1306St.nateldemoura@f5.com nxt_runtime_t *rt; 263*1306St.nateldemoura@f5.com nxt_clone_map_entry_t m; 264*1306St.nateldemoura@f5.com 265*1306St.nateldemoura@f5.com if (map->size == 0) { 266*1306St.nateldemoura@f5.com return NXT_OK; 267*1306St.nateldemoura@f5.com } 268*1306St.nateldemoura@f5.com 269*1306St.nateldemoura@f5.com rt = task->thread->runtime; 270*1306St.nateldemoura@f5.com 271*1306St.nateldemoura@f5.com if (!rt->capabilities.setid) { 272*1306St.nateldemoura@f5.com if (nxt_slow_path(map->size > 1)) { 273*1306St.nateldemoura@f5.com nxt_log(task, NXT_LOG_NOTICE, "\"uidmap\" field has %d entries " 274*1306St.nateldemoura@f5.com "but unprivileged unit has a maximum of 1 map.", 275*1306St.nateldemoura@f5.com map->size); 276*1306St.nateldemoura@f5.com 277*1306St.nateldemoura@f5.com return NXT_ERROR; 278*1306St.nateldemoura@f5.com } 279*1306St.nateldemoura@f5.com 280*1306St.nateldemoura@f5.com id = map->map[0].host; 281*1306St.nateldemoura@f5.com 282*1306St.nateldemoura@f5.com if (nxt_slow_path((nxt_uid_t) id != nxt_euid)) { 283*1306St.nateldemoura@f5.com nxt_log(task, NXT_LOG_NOTICE, "\"uidmap\" field has an entry for " 284*1306St.nateldemoura@f5.com "host uid %d but unprivileged unit can only map itself " 285*1306St.nateldemoura@f5.com "(uid %d) into child namespaces.", id, nxt_euid); 286*1306St.nateldemoura@f5.com 287*1306St.nateldemoura@f5.com return NXT_ERROR; 288*1306St.nateldemoura@f5.com } 289*1306St.nateldemoura@f5.com 290*1306St.nateldemoura@f5.com return NXT_OK; 291*1306St.nateldemoura@f5.com } 292*1306St.nateldemoura@f5.com 293*1306St.nateldemoura@f5.com for (i = 0; i < map->size; i++) { 294*1306St.nateldemoura@f5.com m = map->map[i]; 295*1306St.nateldemoura@f5.com 296*1306St.nateldemoura@f5.com if (creds->uid >= (nxt_uid_t) m.container 297*1306St.nateldemoura@f5.com && creds->uid < (nxt_uid_t) (m.container + m.size)) 298*1306St.nateldemoura@f5.com { 299*1306St.nateldemoura@f5.com return NXT_OK; 300*1306St.nateldemoura@f5.com } 301*1306St.nateldemoura@f5.com } 302*1306St.nateldemoura@f5.com 303*1306St.nateldemoura@f5.com nxt_log(task, NXT_LOG_NOTICE, "\"uidmap\" field has no \"container\" " 304*1306St.nateldemoura@f5.com "entry for user \"%s\" (uid %d)", creds->user, creds->uid); 305*1306St.nateldemoura@f5.com 306*1306St.nateldemoura@f5.com return NXT_ERROR; 307*1306St.nateldemoura@f5.com } 308*1306St.nateldemoura@f5.com 309*1306St.nateldemoura@f5.com 310*1306St.nateldemoura@f5.com nxt_int_t 311*1306St.nateldemoura@f5.com nxt_clone_vldt_credential_gidmap(nxt_task_t *task, 312*1306St.nateldemoura@f5.com nxt_clone_credential_map_t *map, nxt_credential_t *creds) 313*1306St.nateldemoura@f5.com { 314*1306St.nateldemoura@f5.com nxt_uint_t base_ok, gid_ok, gids_ok; 315*1306St.nateldemoura@f5.com nxt_uint_t i, j; 316*1306St.nateldemoura@f5.com nxt_runtime_t *rt; 317*1306St.nateldemoura@f5.com nxt_clone_map_entry_t m; 318*1306St.nateldemoura@f5.com 319*1306St.nateldemoura@f5.com rt = task->thread->runtime; 320*1306St.nateldemoura@f5.com 321*1306St.nateldemoura@f5.com if (!rt->capabilities.setid) { 322*1306St.nateldemoura@f5.com if (creds->ngroups > 0 323*1306St.nateldemoura@f5.com && !(creds->ngroups == 1 && creds->gids[0] == creds->base_gid)) { 324*1306St.nateldemoura@f5.com nxt_log(task, NXT_LOG_NOTICE, 325*1306St.nateldemoura@f5.com "unprivileged unit disallow supplementary groups for " 326*1306St.nateldemoura@f5.com "new namespace (user \"%s\" has %d group%s).", 327*1306St.nateldemoura@f5.com creds->user, creds->ngroups, 328*1306St.nateldemoura@f5.com creds->ngroups > 1 ? "s" : ""); 329*1306St.nateldemoura@f5.com 330*1306St.nateldemoura@f5.com return NXT_ERROR; 331*1306St.nateldemoura@f5.com } 332*1306St.nateldemoura@f5.com 333*1306St.nateldemoura@f5.com if (map->size == 0) { 334*1306St.nateldemoura@f5.com return NXT_OK; 335*1306St.nateldemoura@f5.com } 336*1306St.nateldemoura@f5.com 337*1306St.nateldemoura@f5.com if (nxt_slow_path(map->size > 1)) { 338*1306St.nateldemoura@f5.com nxt_log(task, NXT_LOG_NOTICE, "\"gidmap\" field has %d entries " 339*1306St.nateldemoura@f5.com "but unprivileged unit has a maximum of 1 map.", 340*1306St.nateldemoura@f5.com map->size); 341*1306St.nateldemoura@f5.com 342*1306St.nateldemoura@f5.com return NXT_ERROR; 343*1306St.nateldemoura@f5.com } 344*1306St.nateldemoura@f5.com 345*1306St.nateldemoura@f5.com m = map->map[0]; 346*1306St.nateldemoura@f5.com 347*1306St.nateldemoura@f5.com if (nxt_slow_path((nxt_gid_t) m.host != nxt_egid)) { 348*1306St.nateldemoura@f5.com nxt_log(task, NXT_LOG_ERR, "\"gidmap\" field has an entry for " 349*1306St.nateldemoura@f5.com "host gid %d but unprivileged unit can only map itself " 350*1306St.nateldemoura@f5.com "(gid %d) into child namespaces.", m.host, nxt_egid); 351*1306St.nateldemoura@f5.com 352*1306St.nateldemoura@f5.com return NXT_ERROR; 353*1306St.nateldemoura@f5.com } 354*1306St.nateldemoura@f5.com 355*1306St.nateldemoura@f5.com if (nxt_slow_path(m.size > 1)) { 356*1306St.nateldemoura@f5.com nxt_log(task, NXT_LOG_ERR, "\"gidmap\" field has an entry with " 357*1306St.nateldemoura@f5.com "\"size\": %d, but for unprivileged unit it must be 1.", 358*1306St.nateldemoura@f5.com m.size); 359*1306St.nateldemoura@f5.com 360*1306St.nateldemoura@f5.com return NXT_ERROR; 361*1306St.nateldemoura@f5.com } 362*1306St.nateldemoura@f5.com 363*1306St.nateldemoura@f5.com if (nxt_slow_path((nxt_gid_t) m.container != creds->base_gid)) { 364*1306St.nateldemoura@f5.com nxt_log(task, NXT_LOG_ERR, 365*1306St.nateldemoura@f5.com "\"gidmap\" field has no \"container\" entry for gid %d.", 366*1306St.nateldemoura@f5.com creds->base_gid); 367*1306St.nateldemoura@f5.com 368*1306St.nateldemoura@f5.com return NXT_ERROR; 369*1306St.nateldemoura@f5.com } 370*1306St.nateldemoura@f5.com 371*1306St.nateldemoura@f5.com return NXT_OK; 372*1306St.nateldemoura@f5.com } 373*1306St.nateldemoura@f5.com 374*1306St.nateldemoura@f5.com if (map->size == 0) { 375*1306St.nateldemoura@f5.com if (creds->ngroups > 0 376*1306St.nateldemoura@f5.com && !(creds->ngroups == 1 && creds->gids[0] == creds->base_gid)) 377*1306St.nateldemoura@f5.com { 378*1306St.nateldemoura@f5.com nxt_log(task, NXT_LOG_ERR, "\"gidmap\" field has no entries " 379*1306St.nateldemoura@f5.com "but user \"%s\" has %d suplementary group%s.", 380*1306St.nateldemoura@f5.com creds->user, creds->ngroups, 381*1306St.nateldemoura@f5.com creds->ngroups > 1 ? "s" : ""); 382*1306St.nateldemoura@f5.com 383*1306St.nateldemoura@f5.com return NXT_ERROR; 384*1306St.nateldemoura@f5.com } 385*1306St.nateldemoura@f5.com 386*1306St.nateldemoura@f5.com return NXT_OK; 387*1306St.nateldemoura@f5.com } 388*1306St.nateldemoura@f5.com 389*1306St.nateldemoura@f5.com base_ok = 0; 390*1306St.nateldemoura@f5.com gids_ok = 0; 391*1306St.nateldemoura@f5.com 392*1306St.nateldemoura@f5.com for (i = 0; i < creds->ngroups; i++) { 393*1306St.nateldemoura@f5.com gid_ok = 0; 394*1306St.nateldemoura@f5.com 395*1306St.nateldemoura@f5.com for (j = 0; j < map->size; j++) { 396*1306St.nateldemoura@f5.com m = map->map[j]; 397*1306St.nateldemoura@f5.com 398*1306St.nateldemoura@f5.com if (!base_ok && creds->base_gid >= (nxt_gid_t) m.container 399*1306St.nateldemoura@f5.com && creds->base_gid < (nxt_gid_t) (m.container+m.size)) 400*1306St.nateldemoura@f5.com { 401*1306St.nateldemoura@f5.com base_ok = 1; 402*1306St.nateldemoura@f5.com } 403*1306St.nateldemoura@f5.com 404*1306St.nateldemoura@f5.com if (creds->gids[i] >= (nxt_gid_t) m.container 405*1306St.nateldemoura@f5.com && creds->gids[i] < (nxt_gid_t) (m.container+m.size)) 406*1306St.nateldemoura@f5.com { 407*1306St.nateldemoura@f5.com gid_ok = 1; 408*1306St.nateldemoura@f5.com break; 409*1306St.nateldemoura@f5.com } 410*1306St.nateldemoura@f5.com } 411*1306St.nateldemoura@f5.com 412*1306St.nateldemoura@f5.com if (nxt_fast_path(gid_ok)) { 413*1306St.nateldemoura@f5.com gids_ok++; 414*1306St.nateldemoura@f5.com } 415*1306St.nateldemoura@f5.com } 416*1306St.nateldemoura@f5.com 417*1306St.nateldemoura@f5.com if (!base_ok) { 418*1306St.nateldemoura@f5.com for (i = 0; i < map->size; i++) { 419*1306St.nateldemoura@f5.com m = map->map[i]; 420*1306St.nateldemoura@f5.com 421*1306St.nateldemoura@f5.com if (creds->base_gid >= (nxt_gid_t) m.container 422*1306St.nateldemoura@f5.com && creds->base_gid < (nxt_gid_t) (m.container+m.size)) 423*1306St.nateldemoura@f5.com { 424*1306St.nateldemoura@f5.com base_ok = 1; 425*1306St.nateldemoura@f5.com break; 426*1306St.nateldemoura@f5.com } 427*1306St.nateldemoura@f5.com } 428*1306St.nateldemoura@f5.com } 429*1306St.nateldemoura@f5.com 430*1306St.nateldemoura@f5.com if (nxt_slow_path(!base_ok)) { 431*1306St.nateldemoura@f5.com nxt_log(task, NXT_LOG_ERR, "\"gidmap\" field has no \"container\" " 432*1306St.nateldemoura@f5.com "entry for gid %d.", creds->base_gid); 433*1306St.nateldemoura@f5.com 434*1306St.nateldemoura@f5.com return NXT_ERROR; 435*1306St.nateldemoura@f5.com } 436*1306St.nateldemoura@f5.com 437*1306St.nateldemoura@f5.com if (nxt_slow_path(gids_ok < creds->ngroups)) { 438*1306St.nateldemoura@f5.com nxt_log(task, NXT_LOG_ERR, "\"gidmap\" field has missing " 439*1306St.nateldemoura@f5.com "suplementary gid mappings (found %d out of %d).", gids_ok, 440*1306St.nateldemoura@f5.com creds->ngroups); 441*1306St.nateldemoura@f5.com 442*1306St.nateldemoura@f5.com return NXT_ERROR; 443*1306St.nateldemoura@f5.com } 444*1306St.nateldemoura@f5.com 445*1306St.nateldemoura@f5.com return NXT_OK; 446*1306St.nateldemoura@f5.com } 447*1306St.nateldemoura@f5.com 4481182St.nateldemoura@f5.com #endif 449