11579St.nateldemoura@f5.com /* 21579St.nateldemoura@f5.com * Copyright (C) NGINX, Inc. 31579St.nateldemoura@f5.com */ 41579St.nateldemoura@f5.com 51579St.nateldemoura@f5.com #include <nxt_main.h> 61579St.nateldemoura@f5.com #include <nxt_application.h> 71579St.nateldemoura@f5.com #include <nxt_process.h> 81579St.nateldemoura@f5.com #include <nxt_isolation.h> 91579St.nateldemoura@f5.com 101579St.nateldemoura@f5.com #if (NXT_HAVE_PIVOT_ROOT) 111579St.nateldemoura@f5.com #include <mntent.h> 121579St.nateldemoura@f5.com #endif 131579St.nateldemoura@f5.com 141579St.nateldemoura@f5.com 151579St.nateldemoura@f5.com static nxt_int_t nxt_isolation_set(nxt_task_t *task, 161579St.nateldemoura@f5.com nxt_conf_value_t *isolation, nxt_process_t *process); 171579St.nateldemoura@f5.com 181579St.nateldemoura@f5.com #if (NXT_HAVE_CLONE) 191579St.nateldemoura@f5.com static nxt_int_t nxt_isolation_set_namespaces(nxt_task_t *task, 201579St.nateldemoura@f5.com nxt_conf_value_t *isolation, nxt_process_t *process); 211579St.nateldemoura@f5.com static nxt_int_t nxt_isolation_clone_flags(nxt_task_t *task, 221579St.nateldemoura@f5.com nxt_conf_value_t *namespaces, nxt_clone_t *clone); 231579St.nateldemoura@f5.com #endif 241579St.nateldemoura@f5.com 251579St.nateldemoura@f5.com #if (NXT_HAVE_CLONE_NEWUSER) 261579St.nateldemoura@f5.com static nxt_int_t nxt_isolation_set_creds(nxt_task_t *task, 271579St.nateldemoura@f5.com nxt_conf_value_t *isolation, nxt_process_t *process); 281579St.nateldemoura@f5.com static nxt_int_t nxt_isolation_credential_map(nxt_task_t *task, 291579St.nateldemoura@f5.com nxt_mp_t *mem_pool, nxt_conf_value_t *map_array, 301579St.nateldemoura@f5.com nxt_clone_credential_map_t *map); 311579St.nateldemoura@f5.com static nxt_int_t nxt_isolation_vldt_creds(nxt_task_t *task, 321579St.nateldemoura@f5.com nxt_process_t *process); 331579St.nateldemoura@f5.com #endif 341579St.nateldemoura@f5.com 351579St.nateldemoura@f5.com #if (NXT_HAVE_ISOLATION_ROOTFS) 361579St.nateldemoura@f5.com static nxt_int_t nxt_isolation_set_rootfs(nxt_task_t *task, 371579St.nateldemoura@f5.com nxt_conf_value_t *isolation, nxt_process_t *process); 381585St.nateldemoura@f5.com static nxt_int_t nxt_isolation_set_automount(nxt_task_t *task, 391585St.nateldemoura@f5.com nxt_conf_value_t *isolation, nxt_process_t *process); 401579St.nateldemoura@f5.com static nxt_int_t nxt_isolation_set_mounts(nxt_task_t *task, 411579St.nateldemoura@f5.com nxt_process_t *process, nxt_str_t *app_type); 421579St.nateldemoura@f5.com static nxt_int_t nxt_isolation_set_lang_mounts(nxt_task_t *task, 431579St.nateldemoura@f5.com nxt_process_t *process, nxt_array_t *syspaths); 441671St.nateldemoura@f5.com static int nxt_cdecl nxt_isolation_mount_compare(const void *v1, 451671St.nateldemoura@f5.com const void *v2); 461579St.nateldemoura@f5.com static void nxt_isolation_unmount_all(nxt_task_t *task, nxt_process_t *process); 471579St.nateldemoura@f5.com 481579St.nateldemoura@f5.com #if (NXT_HAVE_PIVOT_ROOT) && (NXT_HAVE_CLONE_NEWNS) 491579St.nateldemoura@f5.com static nxt_int_t nxt_isolation_pivot_root(nxt_task_t *task, const char *rootfs); 501579St.nateldemoura@f5.com static nxt_int_t nxt_isolation_make_private_mount(nxt_task_t *task, 511579St.nateldemoura@f5.com const char *rootfs); 521579St.nateldemoura@f5.com nxt_inline int nxt_pivot_root(const char *new_root, const char *old_root); 531579St.nateldemoura@f5.com #endif 541579St.nateldemoura@f5.com 551579St.nateldemoura@f5.com static nxt_int_t nxt_isolation_chroot(nxt_task_t *task, const char *path); 561579St.nateldemoura@f5.com #endif 571579St.nateldemoura@f5.com 581579St.nateldemoura@f5.com #if (NXT_HAVE_PR_SET_NO_NEW_PRIVS) 591579St.nateldemoura@f5.com static nxt_int_t nxt_isolation_set_new_privs(nxt_task_t *task, 601579St.nateldemoura@f5.com nxt_conf_value_t *isolation, nxt_process_t *process); 611579St.nateldemoura@f5.com #endif 621579St.nateldemoura@f5.com 631579St.nateldemoura@f5.com 641579St.nateldemoura@f5.com nxt_int_t 651579St.nateldemoura@f5.com nxt_isolation_main_prefork(nxt_task_t *task, nxt_process_t *process, 661579St.nateldemoura@f5.com nxt_mp_t *mp) 671579St.nateldemoura@f5.com { 681579St.nateldemoura@f5.com nxt_int_t cap_setid; 691579St.nateldemoura@f5.com nxt_int_t ret; 701579St.nateldemoura@f5.com nxt_runtime_t *rt; 711579St.nateldemoura@f5.com nxt_common_app_conf_t *app_conf; 721579St.nateldemoura@f5.com 731579St.nateldemoura@f5.com rt = task->thread->runtime; 741579St.nateldemoura@f5.com app_conf = process->data.app; 751579St.nateldemoura@f5.com cap_setid = rt->capabilities.setid; 761579St.nateldemoura@f5.com 771579St.nateldemoura@f5.com if (app_conf->isolation != NULL) { 781579St.nateldemoura@f5.com ret = nxt_isolation_set(task, app_conf->isolation, process); 791579St.nateldemoura@f5.com if (nxt_slow_path(ret != NXT_OK)) { 801579St.nateldemoura@f5.com return ret; 811579St.nateldemoura@f5.com } 821579St.nateldemoura@f5.com } 831579St.nateldemoura@f5.com 841579St.nateldemoura@f5.com #if (NXT_HAVE_CLONE_NEWUSER) 851579St.nateldemoura@f5.com if (nxt_is_clone_flag_set(process->isolation.clone.flags, NEWUSER)) { 861579St.nateldemoura@f5.com cap_setid = 1; 871579St.nateldemoura@f5.com } 881579St.nateldemoura@f5.com #endif 891579St.nateldemoura@f5.com 901579St.nateldemoura@f5.com if (cap_setid) { 911579St.nateldemoura@f5.com ret = nxt_process_creds_set(task, process, &app_conf->user, 921579St.nateldemoura@f5.com &app_conf->group); 931579St.nateldemoura@f5.com 941579St.nateldemoura@f5.com if (nxt_slow_path(ret != NXT_OK)) { 951579St.nateldemoura@f5.com return ret; 961579St.nateldemoura@f5.com } 971579St.nateldemoura@f5.com 981579St.nateldemoura@f5.com } else { 991579St.nateldemoura@f5.com if (!nxt_str_eq(&app_conf->user, (u_char *) rt->user_cred.user, 1001579St.nateldemoura@f5.com nxt_strlen(rt->user_cred.user))) 1011579St.nateldemoura@f5.com { 1021579St.nateldemoura@f5.com nxt_alert(task, "cannot set user \"%V\" for app \"%V\": " 1031579St.nateldemoura@f5.com "missing capabilities", &app_conf->user, &app_conf->name); 1041579St.nateldemoura@f5.com 1051579St.nateldemoura@f5.com return NXT_ERROR; 1061579St.nateldemoura@f5.com } 1071579St.nateldemoura@f5.com 1081579St.nateldemoura@f5.com if (app_conf->group.length > 0 1091579St.nateldemoura@f5.com && !nxt_str_eq(&app_conf->group, (u_char *) rt->group, 1101579St.nateldemoura@f5.com nxt_strlen(rt->group))) 1111579St.nateldemoura@f5.com { 1121579St.nateldemoura@f5.com nxt_alert(task, "cannot set group \"%V\" for app \"%V\": " 1131579St.nateldemoura@f5.com "missing capabilities", &app_conf->group, 1141579St.nateldemoura@f5.com &app_conf->name); 1151579St.nateldemoura@f5.com 1161579St.nateldemoura@f5.com return NXT_ERROR; 1171579St.nateldemoura@f5.com } 1181579St.nateldemoura@f5.com } 1191579St.nateldemoura@f5.com 1201673St.nateldemoura@f5.com #if (NXT_HAVE_ISOLATION_ROOTFS) 1211673St.nateldemoura@f5.com if (process->isolation.rootfs != NULL) { 1221673St.nateldemoura@f5.com nxt_int_t has_mnt; 1231673St.nateldemoura@f5.com 1241673St.nateldemoura@f5.com ret = nxt_isolation_set_mounts(task, process, &app_conf->type); 1251673St.nateldemoura@f5.com if (nxt_slow_path(ret != NXT_OK)) { 1261673St.nateldemoura@f5.com return ret; 1271673St.nateldemoura@f5.com } 1281673St.nateldemoura@f5.com 1291673St.nateldemoura@f5.com has_mnt = 0; 1301673St.nateldemoura@f5.com 1311673St.nateldemoura@f5.com #if (NXT_HAVE_CLONE_NEWNS) 1321673St.nateldemoura@f5.com has_mnt = nxt_is_clone_flag_set(process->isolation.clone.flags, NEWNS); 1331673St.nateldemoura@f5.com #endif 1341673St.nateldemoura@f5.com 1351673St.nateldemoura@f5.com if (process->user_cred->uid == 0 && !has_mnt) { 1361673St.nateldemoura@f5.com nxt_log(task, NXT_LOG_WARN, 1371673St.nateldemoura@f5.com "setting user \"root\" with \"rootfs\" is unsafe without " 1381673St.nateldemoura@f5.com "\"mount\" namespace isolation"); 1391673St.nateldemoura@f5.com } 1401673St.nateldemoura@f5.com } 1411673St.nateldemoura@f5.com #endif 1421673St.nateldemoura@f5.com 1431579St.nateldemoura@f5.com #if (NXT_HAVE_CLONE_NEWUSER) 1441579St.nateldemoura@f5.com ret = nxt_isolation_vldt_creds(task, process); 1451579St.nateldemoura@f5.com if (nxt_slow_path(ret != NXT_OK)) { 1461579St.nateldemoura@f5.com return ret; 1471579St.nateldemoura@f5.com } 1481579St.nateldemoura@f5.com #endif 1491579St.nateldemoura@f5.com 1501579St.nateldemoura@f5.com return NXT_OK; 1511579St.nateldemoura@f5.com } 1521579St.nateldemoura@f5.com 1531579St.nateldemoura@f5.com 1541579St.nateldemoura@f5.com static nxt_int_t 1551579St.nateldemoura@f5.com nxt_isolation_set(nxt_task_t *task, nxt_conf_value_t *isolation, 1561579St.nateldemoura@f5.com nxt_process_t *process) 1571579St.nateldemoura@f5.com { 1581579St.nateldemoura@f5.com #if (NXT_HAVE_CLONE) 1591579St.nateldemoura@f5.com if (nxt_slow_path(nxt_isolation_set_namespaces(task, isolation, process) 1601579St.nateldemoura@f5.com != NXT_OK)) 1611579St.nateldemoura@f5.com { 1621579St.nateldemoura@f5.com return NXT_ERROR; 1631579St.nateldemoura@f5.com } 1641579St.nateldemoura@f5.com #endif 1651579St.nateldemoura@f5.com 1661579St.nateldemoura@f5.com #if (NXT_HAVE_CLONE_NEWUSER) 1671579St.nateldemoura@f5.com if (nxt_slow_path(nxt_isolation_set_creds(task, isolation, process) 1681579St.nateldemoura@f5.com != NXT_OK)) 1691579St.nateldemoura@f5.com { 1701579St.nateldemoura@f5.com return NXT_ERROR; 1711579St.nateldemoura@f5.com } 1721579St.nateldemoura@f5.com #endif 1731579St.nateldemoura@f5.com 1741579St.nateldemoura@f5.com #if (NXT_HAVE_ISOLATION_ROOTFS) 1751579St.nateldemoura@f5.com if (nxt_slow_path(nxt_isolation_set_rootfs(task, isolation, process) 1761579St.nateldemoura@f5.com != NXT_OK)) 1771579St.nateldemoura@f5.com { 1781579St.nateldemoura@f5.com return NXT_ERROR; 1791579St.nateldemoura@f5.com } 1801585St.nateldemoura@f5.com 1811585St.nateldemoura@f5.com if (nxt_slow_path(nxt_isolation_set_automount(task, isolation, process) 1821585St.nateldemoura@f5.com != NXT_OK)) 1831585St.nateldemoura@f5.com { 1841585St.nateldemoura@f5.com return NXT_ERROR; 1851585St.nateldemoura@f5.com } 1861579St.nateldemoura@f5.com #endif 1871579St.nateldemoura@f5.com 1881579St.nateldemoura@f5.com #if (NXT_HAVE_PR_SET_NO_NEW_PRIVS) 1891579St.nateldemoura@f5.com if (nxt_slow_path(nxt_isolation_set_new_privs(task, isolation, process) 1901579St.nateldemoura@f5.com != NXT_OK)) 1911579St.nateldemoura@f5.com { 1921579St.nateldemoura@f5.com return NXT_ERROR; 1931579St.nateldemoura@f5.com } 1941579St.nateldemoura@f5.com #endif 1951579St.nateldemoura@f5.com 1961579St.nateldemoura@f5.com return NXT_OK; 1971579St.nateldemoura@f5.com } 1981579St.nateldemoura@f5.com 1991579St.nateldemoura@f5.com 2001579St.nateldemoura@f5.com #if (NXT_HAVE_CLONE) 2011579St.nateldemoura@f5.com 2021579St.nateldemoura@f5.com static nxt_int_t 2031579St.nateldemoura@f5.com nxt_isolation_set_namespaces(nxt_task_t *task, nxt_conf_value_t *isolation, 2041579St.nateldemoura@f5.com nxt_process_t *process) 2051579St.nateldemoura@f5.com { 2061579St.nateldemoura@f5.com nxt_int_t ret; 2071579St.nateldemoura@f5.com nxt_conf_value_t *obj; 2081579St.nateldemoura@f5.com 2091579St.nateldemoura@f5.com static nxt_str_t nsname = nxt_string("namespaces"); 2101579St.nateldemoura@f5.com 2111579St.nateldemoura@f5.com obj = nxt_conf_get_object_member(isolation, &nsname, NULL); 2121579St.nateldemoura@f5.com if (obj != NULL) { 2131579St.nateldemoura@f5.com ret = nxt_isolation_clone_flags(task, obj, &process->isolation.clone); 2141579St.nateldemoura@f5.com if (nxt_slow_path(ret != NXT_OK)) { 2151579St.nateldemoura@f5.com return NXT_ERROR; 2161579St.nateldemoura@f5.com } 2171579St.nateldemoura@f5.com } 2181579St.nateldemoura@f5.com 2191579St.nateldemoura@f5.com return NXT_OK; 2201579St.nateldemoura@f5.com } 2211579St.nateldemoura@f5.com 2221579St.nateldemoura@f5.com #endif 2231579St.nateldemoura@f5.com 2241579St.nateldemoura@f5.com 2251579St.nateldemoura@f5.com #if (NXT_HAVE_CLONE_NEWUSER) 2261579St.nateldemoura@f5.com 2271579St.nateldemoura@f5.com static nxt_int_t 2281579St.nateldemoura@f5.com nxt_isolation_set_creds(nxt_task_t *task, nxt_conf_value_t *isolation, 2291579St.nateldemoura@f5.com nxt_process_t *process) 2301579St.nateldemoura@f5.com { 2311579St.nateldemoura@f5.com nxt_int_t ret; 2321579St.nateldemoura@f5.com nxt_clone_t *clone; 2331579St.nateldemoura@f5.com nxt_conf_value_t *array; 2341579St.nateldemoura@f5.com 2351579St.nateldemoura@f5.com static nxt_str_t uidname = nxt_string("uidmap"); 2361579St.nateldemoura@f5.com static nxt_str_t gidname = nxt_string("gidmap"); 2371579St.nateldemoura@f5.com 2381579St.nateldemoura@f5.com clone = &process->isolation.clone; 2391579St.nateldemoura@f5.com 2401579St.nateldemoura@f5.com array = nxt_conf_get_object_member(isolation, &uidname, NULL); 2411579St.nateldemoura@f5.com if (array != NULL) { 2421579St.nateldemoura@f5.com ret = nxt_isolation_credential_map(task, process->mem_pool, array, 2431579St.nateldemoura@f5.com &clone->uidmap); 2441579St.nateldemoura@f5.com 2451579St.nateldemoura@f5.com if (nxt_slow_path(ret != NXT_OK)) { 2461579St.nateldemoura@f5.com return NXT_ERROR; 2471579St.nateldemoura@f5.com } 2481579St.nateldemoura@f5.com } 2491579St.nateldemoura@f5.com 2501579St.nateldemoura@f5.com array = nxt_conf_get_object_member(isolation, &gidname, NULL); 2511579St.nateldemoura@f5.com if (array != NULL) { 2521579St.nateldemoura@f5.com ret = nxt_isolation_credential_map(task, process->mem_pool, array, 2531579St.nateldemoura@f5.com &clone->gidmap); 2541579St.nateldemoura@f5.com 2551579St.nateldemoura@f5.com if (nxt_slow_path(ret != NXT_OK)) { 2561579St.nateldemoura@f5.com return NXT_ERROR; 2571579St.nateldemoura@f5.com } 2581579St.nateldemoura@f5.com } 2591579St.nateldemoura@f5.com 2601579St.nateldemoura@f5.com return NXT_OK; 2611579St.nateldemoura@f5.com } 2621579St.nateldemoura@f5.com 2631579St.nateldemoura@f5.com 2641579St.nateldemoura@f5.com static nxt_int_t 2651579St.nateldemoura@f5.com nxt_isolation_credential_map(nxt_task_t *task, nxt_mp_t *mp, 2661579St.nateldemoura@f5.com nxt_conf_value_t *map_array, nxt_clone_credential_map_t *map) 2671579St.nateldemoura@f5.com { 2681579St.nateldemoura@f5.com nxt_int_t ret; 2691579St.nateldemoura@f5.com nxt_uint_t i; 2701579St.nateldemoura@f5.com nxt_conf_value_t *obj; 2711579St.nateldemoura@f5.com 2721579St.nateldemoura@f5.com static nxt_conf_map_t nxt_clone_map_entry_conf[] = { 2731579St.nateldemoura@f5.com { 2741579St.nateldemoura@f5.com nxt_string("container"), 2751579St.nateldemoura@f5.com NXT_CONF_MAP_INT, 2761579St.nateldemoura@f5.com offsetof(nxt_clone_map_entry_t, container), 2771579St.nateldemoura@f5.com }, 2781579St.nateldemoura@f5.com 2791579St.nateldemoura@f5.com { 2801579St.nateldemoura@f5.com nxt_string("host"), 2811579St.nateldemoura@f5.com NXT_CONF_MAP_INT, 2821579St.nateldemoura@f5.com offsetof(nxt_clone_map_entry_t, host), 2831579St.nateldemoura@f5.com }, 2841579St.nateldemoura@f5.com 2851579St.nateldemoura@f5.com { 2861579St.nateldemoura@f5.com nxt_string("size"), 2871579St.nateldemoura@f5.com NXT_CONF_MAP_INT, 2881579St.nateldemoura@f5.com offsetof(nxt_clone_map_entry_t, size), 2891579St.nateldemoura@f5.com }, 2901579St.nateldemoura@f5.com }; 2911579St.nateldemoura@f5.com 2921579St.nateldemoura@f5.com map->size = nxt_conf_array_elements_count(map_array); 2931579St.nateldemoura@f5.com 2941579St.nateldemoura@f5.com if (map->size == 0) { 2951579St.nateldemoura@f5.com return NXT_OK; 2961579St.nateldemoura@f5.com } 2971579St.nateldemoura@f5.com 2981579St.nateldemoura@f5.com map->map = nxt_mp_alloc(mp, map->size * sizeof(nxt_clone_map_entry_t)); 2991579St.nateldemoura@f5.com if (nxt_slow_path(map->map == NULL)) { 3001579St.nateldemoura@f5.com return NXT_ERROR; 3011579St.nateldemoura@f5.com } 3021579St.nateldemoura@f5.com 3031579St.nateldemoura@f5.com for (i = 0; i < map->size; i++) { 3041579St.nateldemoura@f5.com obj = nxt_conf_get_array_element(map_array, i); 3051579St.nateldemoura@f5.com 3061579St.nateldemoura@f5.com ret = nxt_conf_map_object(mp, obj, nxt_clone_map_entry_conf, 3071579St.nateldemoura@f5.com nxt_nitems(nxt_clone_map_entry_conf), 3081579St.nateldemoura@f5.com map->map + i); 3091579St.nateldemoura@f5.com if (nxt_slow_path(ret != NXT_OK)) { 3101579St.nateldemoura@f5.com nxt_alert(task, "clone map entry map error"); 3111579St.nateldemoura@f5.com return NXT_ERROR; 3121579St.nateldemoura@f5.com } 3131579St.nateldemoura@f5.com } 3141579St.nateldemoura@f5.com 3151579St.nateldemoura@f5.com return NXT_OK; 3161579St.nateldemoura@f5.com } 3171579St.nateldemoura@f5.com 3181579St.nateldemoura@f5.com 3191579St.nateldemoura@f5.com static nxt_int_t 3201579St.nateldemoura@f5.com nxt_isolation_vldt_creds(nxt_task_t *task, nxt_process_t *process) 3211579St.nateldemoura@f5.com { 3221579St.nateldemoura@f5.com nxt_int_t ret; 3231579St.nateldemoura@f5.com nxt_clone_t *clone; 3241579St.nateldemoura@f5.com nxt_credential_t *creds; 3251579St.nateldemoura@f5.com 3261579St.nateldemoura@f5.com clone = &process->isolation.clone; 3271579St.nateldemoura@f5.com creds = process->user_cred; 3281579St.nateldemoura@f5.com 3291579St.nateldemoura@f5.com if (clone->uidmap.size == 0 && clone->gidmap.size == 0) { 3301579St.nateldemoura@f5.com return NXT_OK; 3311579St.nateldemoura@f5.com } 3321579St.nateldemoura@f5.com 3331579St.nateldemoura@f5.com if (!nxt_is_clone_flag_set(clone->flags, NEWUSER)) { 3341579St.nateldemoura@f5.com if (nxt_slow_path(clone->uidmap.size > 0)) { 3351579St.nateldemoura@f5.com nxt_log(task, NXT_LOG_ERR, "\"uidmap\" is set but " 3361579St.nateldemoura@f5.com "\"isolation.namespaces.credential\" is false or unset"); 3371579St.nateldemoura@f5.com 3381579St.nateldemoura@f5.com return NXT_ERROR; 3391579St.nateldemoura@f5.com } 3401579St.nateldemoura@f5.com 3411579St.nateldemoura@f5.com if (nxt_slow_path(clone->gidmap.size > 0)) { 3421579St.nateldemoura@f5.com nxt_log(task, NXT_LOG_ERR, "\"gidmap\" is set but " 3431579St.nateldemoura@f5.com "\"isolation.namespaces.credential\" is false or unset"); 3441579St.nateldemoura@f5.com 3451579St.nateldemoura@f5.com return NXT_ERROR; 3461579St.nateldemoura@f5.com } 3471579St.nateldemoura@f5.com 3481579St.nateldemoura@f5.com return NXT_OK; 3491579St.nateldemoura@f5.com } 3501579St.nateldemoura@f5.com 3511579St.nateldemoura@f5.com ret = nxt_clone_vldt_credential_uidmap(task, &clone->uidmap, creds); 3521579St.nateldemoura@f5.com if (nxt_slow_path(ret != NXT_OK)) { 3531579St.nateldemoura@f5.com return NXT_ERROR; 3541579St.nateldemoura@f5.com } 3551579St.nateldemoura@f5.com 3561579St.nateldemoura@f5.com return nxt_clone_vldt_credential_gidmap(task, &clone->gidmap, creds); 3571579St.nateldemoura@f5.com } 3581579St.nateldemoura@f5.com 3591579St.nateldemoura@f5.com #endif 3601579St.nateldemoura@f5.com 3611579St.nateldemoura@f5.com 3621579St.nateldemoura@f5.com #if (NXT_HAVE_CLONE) 3631579St.nateldemoura@f5.com 3641579St.nateldemoura@f5.com static nxt_int_t 3651579St.nateldemoura@f5.com nxt_isolation_clone_flags(nxt_task_t *task, nxt_conf_value_t *namespaces, 3661579St.nateldemoura@f5.com nxt_clone_t *clone) 3671579St.nateldemoura@f5.com { 3681579St.nateldemoura@f5.com uint32_t index; 3691579St.nateldemoura@f5.com nxt_str_t name; 3701579St.nateldemoura@f5.com nxt_int_t flag; 3711579St.nateldemoura@f5.com nxt_conf_value_t *value; 3721579St.nateldemoura@f5.com 3731579St.nateldemoura@f5.com index = 0; 3741579St.nateldemoura@f5.com 3751579St.nateldemoura@f5.com for ( ;; ) { 3761579St.nateldemoura@f5.com value = nxt_conf_next_object_member(namespaces, &name, &index); 3771579St.nateldemoura@f5.com 3781579St.nateldemoura@f5.com if (value == NULL) { 3791579St.nateldemoura@f5.com break; 3801579St.nateldemoura@f5.com } 3811579St.nateldemoura@f5.com 3821579St.nateldemoura@f5.com flag = 0; 3831579St.nateldemoura@f5.com 3841579St.nateldemoura@f5.com #if (NXT_HAVE_CLONE_NEWUSER) 3851579St.nateldemoura@f5.com if (nxt_str_eq(&name, "credential", 10)) { 3861579St.nateldemoura@f5.com flag = CLONE_NEWUSER; 3871579St.nateldemoura@f5.com } 3881579St.nateldemoura@f5.com #endif 3891579St.nateldemoura@f5.com 3901579St.nateldemoura@f5.com #if (NXT_HAVE_CLONE_NEWPID) 3911579St.nateldemoura@f5.com if (nxt_str_eq(&name, "pid", 3)) { 3921579St.nateldemoura@f5.com flag = CLONE_NEWPID; 3931579St.nateldemoura@f5.com } 3941579St.nateldemoura@f5.com #endif 3951579St.nateldemoura@f5.com 3961579St.nateldemoura@f5.com #if (NXT_HAVE_CLONE_NEWNET) 3971579St.nateldemoura@f5.com if (nxt_str_eq(&name, "network", 7)) { 3981579St.nateldemoura@f5.com flag = CLONE_NEWNET; 3991579St.nateldemoura@f5.com } 4001579St.nateldemoura@f5.com #endif 4011579St.nateldemoura@f5.com 4021579St.nateldemoura@f5.com #if (NXT_HAVE_CLONE_NEWUTS) 4031579St.nateldemoura@f5.com if (nxt_str_eq(&name, "uname", 5)) { 4041579St.nateldemoura@f5.com flag = CLONE_NEWUTS; 4051579St.nateldemoura@f5.com } 4061579St.nateldemoura@f5.com #endif 4071579St.nateldemoura@f5.com 4081579St.nateldemoura@f5.com #if (NXT_HAVE_CLONE_NEWNS) 4091579St.nateldemoura@f5.com if (nxt_str_eq(&name, "mount", 5)) { 4101579St.nateldemoura@f5.com flag = CLONE_NEWNS; 4111579St.nateldemoura@f5.com } 4121579St.nateldemoura@f5.com #endif 4131579St.nateldemoura@f5.com 4141579St.nateldemoura@f5.com #if (NXT_HAVE_CLONE_NEWCGROUP) 4151579St.nateldemoura@f5.com if (nxt_str_eq(&name, "cgroup", 6)) { 4161579St.nateldemoura@f5.com flag = CLONE_NEWCGROUP; 4171579St.nateldemoura@f5.com } 4181579St.nateldemoura@f5.com #endif 4191579St.nateldemoura@f5.com 4201579St.nateldemoura@f5.com if (!flag) { 4211579St.nateldemoura@f5.com nxt_alert(task, "unknown namespace flag: \"%V\"", &name); 4221579St.nateldemoura@f5.com return NXT_ERROR; 4231579St.nateldemoura@f5.com } 4241579St.nateldemoura@f5.com 4251579St.nateldemoura@f5.com if (nxt_conf_get_boolean(value)) { 4261579St.nateldemoura@f5.com clone->flags |= flag; 4271579St.nateldemoura@f5.com } 4281579St.nateldemoura@f5.com } 4291579St.nateldemoura@f5.com 4301579St.nateldemoura@f5.com return NXT_OK; 4311579St.nateldemoura@f5.com } 4321579St.nateldemoura@f5.com 4331579St.nateldemoura@f5.com #endif 4341579St.nateldemoura@f5.com 4351579St.nateldemoura@f5.com 4361579St.nateldemoura@f5.com #if (NXT_HAVE_ISOLATION_ROOTFS) 4371579St.nateldemoura@f5.com 4381579St.nateldemoura@f5.com static nxt_int_t 4391579St.nateldemoura@f5.com nxt_isolation_set_rootfs(nxt_task_t *task, nxt_conf_value_t *isolation, 4401579St.nateldemoura@f5.com nxt_process_t *process) 4411579St.nateldemoura@f5.com { 4421579St.nateldemoura@f5.com nxt_str_t str; 4431579St.nateldemoura@f5.com nxt_conf_value_t *obj; 4441579St.nateldemoura@f5.com 4451579St.nateldemoura@f5.com static nxt_str_t rootfs_name = nxt_string("rootfs"); 4461579St.nateldemoura@f5.com 4471579St.nateldemoura@f5.com obj = nxt_conf_get_object_member(isolation, &rootfs_name, NULL); 4481579St.nateldemoura@f5.com if (obj != NULL) { 4491579St.nateldemoura@f5.com nxt_conf_get_string(obj, &str); 4501579St.nateldemoura@f5.com 4511579St.nateldemoura@f5.com if (nxt_slow_path(str.length <= 1 || str.start[0] != '/')) { 4521579St.nateldemoura@f5.com nxt_log(task, NXT_LOG_ERR, "rootfs requires an absolute path other " 4531579St.nateldemoura@f5.com "than \"/\" but given \"%V\"", &str); 4541579St.nateldemoura@f5.com 4551579St.nateldemoura@f5.com return NXT_ERROR; 4561579St.nateldemoura@f5.com } 4571579St.nateldemoura@f5.com 4581579St.nateldemoura@f5.com if (str.start[str.length - 1] == '/') { 4591579St.nateldemoura@f5.com str.length--; 4601579St.nateldemoura@f5.com } 4611579St.nateldemoura@f5.com 4621579St.nateldemoura@f5.com process->isolation.rootfs = nxt_mp_alloc(process->mem_pool, 4631579St.nateldemoura@f5.com str.length + 1); 4641579St.nateldemoura@f5.com 4651579St.nateldemoura@f5.com if (nxt_slow_path(process->isolation.rootfs == NULL)) { 4661579St.nateldemoura@f5.com return NXT_ERROR; 4671579St.nateldemoura@f5.com } 4681579St.nateldemoura@f5.com 4691579St.nateldemoura@f5.com nxt_memcpy(process->isolation.rootfs, str.start, str.length); 4701579St.nateldemoura@f5.com 4711579St.nateldemoura@f5.com process->isolation.rootfs[str.length] = '\0'; 4721579St.nateldemoura@f5.com } 4731579St.nateldemoura@f5.com 4741579St.nateldemoura@f5.com return NXT_OK; 4751579St.nateldemoura@f5.com } 4761579St.nateldemoura@f5.com 4771579St.nateldemoura@f5.com 4781579St.nateldemoura@f5.com static nxt_int_t 4791585St.nateldemoura@f5.com nxt_isolation_set_automount(nxt_task_t *task, nxt_conf_value_t *isolation, 4801585St.nateldemoura@f5.com nxt_process_t *process) 4811585St.nateldemoura@f5.com { 4821585St.nateldemoura@f5.com nxt_conf_value_t *conf, *value; 4831585St.nateldemoura@f5.com nxt_process_automount_t *automount; 4841585St.nateldemoura@f5.com 4851585St.nateldemoura@f5.com static nxt_str_t automount_name = nxt_string("automount"); 4861585St.nateldemoura@f5.com static nxt_str_t langdeps_name = nxt_string("language_deps"); 4871704St.nateldemoura@f5.com static nxt_str_t tmp_name = nxt_string("tmpfs"); 488*1708St.nateldemoura@f5.com static nxt_str_t proc_name = nxt_string("procfs"); 4891585St.nateldemoura@f5.com 4901585St.nateldemoura@f5.com automount = &process->isolation.automount; 4911585St.nateldemoura@f5.com 4921585St.nateldemoura@f5.com automount->language_deps = 1; 4931704St.nateldemoura@f5.com automount->tmpfs = 1; 494*1708St.nateldemoura@f5.com automount->procfs = 1; 4951585St.nateldemoura@f5.com 4961585St.nateldemoura@f5.com conf = nxt_conf_get_object_member(isolation, &automount_name, NULL); 4971585St.nateldemoura@f5.com if (conf != NULL) { 4981585St.nateldemoura@f5.com value = nxt_conf_get_object_member(conf, &langdeps_name, NULL); 4991585St.nateldemoura@f5.com if (value != NULL) { 5001585St.nateldemoura@f5.com automount->language_deps = nxt_conf_get_boolean(value); 5011585St.nateldemoura@f5.com } 5021704St.nateldemoura@f5.com 5031704St.nateldemoura@f5.com value = nxt_conf_get_object_member(conf, &tmp_name, NULL); 5041704St.nateldemoura@f5.com if (value != NULL) { 5051704St.nateldemoura@f5.com automount->tmpfs = nxt_conf_get_boolean(value); 5061704St.nateldemoura@f5.com } 507*1708St.nateldemoura@f5.com 508*1708St.nateldemoura@f5.com value = nxt_conf_get_object_member(conf, &proc_name, NULL); 509*1708St.nateldemoura@f5.com if (value != NULL) { 510*1708St.nateldemoura@f5.com automount->procfs = nxt_conf_get_boolean(value); 511*1708St.nateldemoura@f5.com } 5121585St.nateldemoura@f5.com } 5131585St.nateldemoura@f5.com 5141585St.nateldemoura@f5.com return NXT_OK; 5151585St.nateldemoura@f5.com } 5161585St.nateldemoura@f5.com 5171585St.nateldemoura@f5.com 5181585St.nateldemoura@f5.com static nxt_int_t 5191579St.nateldemoura@f5.com nxt_isolation_set_mounts(nxt_task_t *task, nxt_process_t *process, 5201579St.nateldemoura@f5.com nxt_str_t *app_type) 5211579St.nateldemoura@f5.com { 5221579St.nateldemoura@f5.com nxt_int_t ret, cap_chroot; 5231579St.nateldemoura@f5.com nxt_runtime_t *rt; 5241579St.nateldemoura@f5.com nxt_app_lang_module_t *lang; 5251579St.nateldemoura@f5.com 5261579St.nateldemoura@f5.com rt = task->thread->runtime; 5271579St.nateldemoura@f5.com cap_chroot = rt->capabilities.chroot; 5281579St.nateldemoura@f5.com lang = nxt_app_lang_module(rt, app_type); 5291579St.nateldemoura@f5.com 5301579St.nateldemoura@f5.com nxt_assert(lang != NULL); 5311579St.nateldemoura@f5.com 5321579St.nateldemoura@f5.com #if (NXT_HAVE_CLONE_NEWUSER) 5331579St.nateldemoura@f5.com if (nxt_is_clone_flag_set(process->isolation.clone.flags, NEWUSER)) { 5341579St.nateldemoura@f5.com cap_chroot = 1; 5351579St.nateldemoura@f5.com } 5361579St.nateldemoura@f5.com #endif 5371579St.nateldemoura@f5.com 5381579St.nateldemoura@f5.com if (!cap_chroot) { 5391579St.nateldemoura@f5.com nxt_log(task, NXT_LOG_ERR, "The \"rootfs\" field requires privileges"); 5401579St.nateldemoura@f5.com return NXT_ERROR; 5411579St.nateldemoura@f5.com } 5421579St.nateldemoura@f5.com 5431580St.nateldemoura@f5.com ret = nxt_isolation_set_lang_mounts(task, process, lang->mounts); 5441580St.nateldemoura@f5.com if (nxt_slow_path(ret != NXT_OK)) { 5451580St.nateldemoura@f5.com return NXT_ERROR; 5461580St.nateldemoura@f5.com } 5471579St.nateldemoura@f5.com 5481580St.nateldemoura@f5.com process->isolation.cleanup = nxt_isolation_unmount_all; 5491579St.nateldemoura@f5.com 5501579St.nateldemoura@f5.com return NXT_OK; 5511579St.nateldemoura@f5.com } 5521579St.nateldemoura@f5.com 5531579St.nateldemoura@f5.com 5541579St.nateldemoura@f5.com static nxt_int_t 5551579St.nateldemoura@f5.com nxt_isolation_set_lang_mounts(nxt_task_t *task, nxt_process_t *process, 5561579St.nateldemoura@f5.com nxt_array_t *lang_mounts) 5571579St.nateldemoura@f5.com { 5581579St.nateldemoura@f5.com u_char *p; 5591579St.nateldemoura@f5.com size_t i, n, rootfs_len, len; 5601579St.nateldemoura@f5.com nxt_mp_t *mp; 5611579St.nateldemoura@f5.com nxt_array_t *mounts; 5621579St.nateldemoura@f5.com const u_char *rootfs; 5631579St.nateldemoura@f5.com nxt_fs_mount_t *mnt, *lang_mnt; 5641579St.nateldemoura@f5.com 5651579St.nateldemoura@f5.com mp = process->mem_pool; 5661579St.nateldemoura@f5.com 5671579St.nateldemoura@f5.com /* copy to init mem pool */ 5681579St.nateldemoura@f5.com mounts = nxt_array_copy(mp, NULL, lang_mounts); 5691579St.nateldemoura@f5.com if (mounts == NULL) { 5701579St.nateldemoura@f5.com return NXT_ERROR; 5711579St.nateldemoura@f5.com } 5721579St.nateldemoura@f5.com 5731579St.nateldemoura@f5.com n = mounts->nelts; 5741579St.nateldemoura@f5.com mnt = mounts->elts; 5751579St.nateldemoura@f5.com lang_mnt = lang_mounts->elts; 5761579St.nateldemoura@f5.com 5771580St.nateldemoura@f5.com rootfs = process->isolation.rootfs; 5781580St.nateldemoura@f5.com rootfs_len = nxt_strlen(rootfs); 5791580St.nateldemoura@f5.com 5801579St.nateldemoura@f5.com for (i = 0; i < n; i++) { 5811579St.nateldemoura@f5.com len = nxt_strlen(lang_mnt[i].dst); 5821579St.nateldemoura@f5.com 5831579St.nateldemoura@f5.com mnt[i].dst = nxt_mp_alloc(mp, rootfs_len + len + 1); 5841580St.nateldemoura@f5.com if (nxt_slow_path(mnt[i].dst == NULL)) { 5851579St.nateldemoura@f5.com return NXT_ERROR; 5861579St.nateldemoura@f5.com } 5871579St.nateldemoura@f5.com 5881579St.nateldemoura@f5.com p = nxt_cpymem(mnt[i].dst, rootfs, rootfs_len); 5891579St.nateldemoura@f5.com p = nxt_cpymem(p, lang_mnt[i].dst, len); 5901579St.nateldemoura@f5.com *p = '\0'; 5911579St.nateldemoura@f5.com } 5921579St.nateldemoura@f5.com 5931704St.nateldemoura@f5.com if (process->isolation.automount.tmpfs) { 5941704St.nateldemoura@f5.com mnt = nxt_array_add(mounts); 5951704St.nateldemoura@f5.com if (nxt_slow_path(mnt == NULL)) { 5961704St.nateldemoura@f5.com return NXT_ERROR; 5971704St.nateldemoura@f5.com } 5981580St.nateldemoura@f5.com 5991704St.nateldemoura@f5.com mnt->src = (u_char *) "tmpfs"; 6001704St.nateldemoura@f5.com mnt->name = (u_char *) "tmpfs"; 6011704St.nateldemoura@f5.com mnt->type = NXT_FS_TMP; 6021704St.nateldemoura@f5.com mnt->flags = (NXT_FS_FLAGS_NOSUID 6031704St.nateldemoura@f5.com | NXT_FS_FLAGS_NODEV 6041704St.nateldemoura@f5.com | NXT_FS_FLAGS_NOEXEC); 6051704St.nateldemoura@f5.com mnt->data = (u_char *) "size=1m,mode=777"; 6061704St.nateldemoura@f5.com mnt->builtin = 1; 6071704St.nateldemoura@f5.com mnt->deps = 0; 6081580St.nateldemoura@f5.com 6091704St.nateldemoura@f5.com mnt->dst = nxt_mp_nget(mp, rootfs_len + nxt_length("/tmp") + 1); 6101704St.nateldemoura@f5.com if (nxt_slow_path(mnt->dst == NULL)) { 6111704St.nateldemoura@f5.com return NXT_ERROR; 6121704St.nateldemoura@f5.com } 6131704St.nateldemoura@f5.com 6141704St.nateldemoura@f5.com p = nxt_cpymem(mnt->dst, rootfs, rootfs_len); 6151704St.nateldemoura@f5.com p = nxt_cpymem(p, "/tmp", 4); 6161704St.nateldemoura@f5.com *p = '\0'; 6171580St.nateldemoura@f5.com } 6181580St.nateldemoura@f5.com 619*1708St.nateldemoura@f5.com if (process->isolation.automount.procfs) { 620*1708St.nateldemoura@f5.com mnt = nxt_array_add(mounts); 621*1708St.nateldemoura@f5.com if (nxt_slow_path(mnt == NULL)) { 622*1708St.nateldemoura@f5.com return NXT_ERROR; 623*1708St.nateldemoura@f5.com } 6241580St.nateldemoura@f5.com 625*1708St.nateldemoura@f5.com mnt->name = (u_char *) "proc"; 626*1708St.nateldemoura@f5.com mnt->type = NXT_FS_PROC; 627*1708St.nateldemoura@f5.com mnt->src = (u_char *) "none"; 628*1708St.nateldemoura@f5.com mnt->dst = nxt_mp_nget(mp, rootfs_len + nxt_length("/proc") + 1); 629*1708St.nateldemoura@f5.com if (nxt_slow_path(mnt->dst == NULL)) { 630*1708St.nateldemoura@f5.com return NXT_ERROR; 631*1708St.nateldemoura@f5.com } 6321580St.nateldemoura@f5.com 633*1708St.nateldemoura@f5.com p = nxt_cpymem(mnt->dst, rootfs, rootfs_len); 634*1708St.nateldemoura@f5.com p = nxt_cpymem(p, "/proc", 5); 635*1708St.nateldemoura@f5.com *p = '\0'; 6361580St.nateldemoura@f5.com 637*1708St.nateldemoura@f5.com mnt->data = (u_char *) ""; 638*1708St.nateldemoura@f5.com mnt->flags = NXT_FS_FLAGS_NOEXEC | NXT_FS_FLAGS_NOSUID; 639*1708St.nateldemoura@f5.com mnt->builtin = 1; 640*1708St.nateldemoura@f5.com mnt->deps = 0; 641*1708St.nateldemoura@f5.com } 6421580St.nateldemoura@f5.com 6431671St.nateldemoura@f5.com qsort(mounts->elts, mounts->nelts, sizeof(nxt_fs_mount_t), 6441671St.nateldemoura@f5.com nxt_isolation_mount_compare); 6451671St.nateldemoura@f5.com 6461579St.nateldemoura@f5.com process->isolation.mounts = mounts; 6471579St.nateldemoura@f5.com 6481579St.nateldemoura@f5.com return NXT_OK; 6491579St.nateldemoura@f5.com } 6501579St.nateldemoura@f5.com 6511579St.nateldemoura@f5.com 6521671St.nateldemoura@f5.com static int nxt_cdecl 6531671St.nateldemoura@f5.com nxt_isolation_mount_compare(const void *v1, const void *v2) 6541671St.nateldemoura@f5.com { 6551671St.nateldemoura@f5.com const nxt_fs_mount_t *mnt1, *mnt2; 6561671St.nateldemoura@f5.com 6571671St.nateldemoura@f5.com mnt1 = v1; 6581671St.nateldemoura@f5.com mnt2 = v2; 6591671St.nateldemoura@f5.com 6601671St.nateldemoura@f5.com return nxt_strlen(mnt1->src) > nxt_strlen(mnt2->src); 6611671St.nateldemoura@f5.com } 6621671St.nateldemoura@f5.com 6631671St.nateldemoura@f5.com 6641579St.nateldemoura@f5.com void 6651579St.nateldemoura@f5.com nxt_isolation_unmount_all(nxt_task_t *task, nxt_process_t *process) 6661579St.nateldemoura@f5.com { 6671671St.nateldemoura@f5.com size_t n; 6681585St.nateldemoura@f5.com nxt_array_t *mounts; 6691671St.nateldemoura@f5.com nxt_runtime_t *rt; 6701585St.nateldemoura@f5.com nxt_fs_mount_t *mnt; 6711585St.nateldemoura@f5.com nxt_process_automount_t *automount; 6721579St.nateldemoura@f5.com 6731671St.nateldemoura@f5.com rt = task->thread->runtime; 6741671St.nateldemoura@f5.com 6751671St.nateldemoura@f5.com if (!rt->capabilities.setid) { 6761671St.nateldemoura@f5.com return; 6771671St.nateldemoura@f5.com } 6781671St.nateldemoura@f5.com 6791671St.nateldemoura@f5.com #if (NXT_HAVE_CLONE_NEWNS) 6801671St.nateldemoura@f5.com if (nxt_is_clone_flag_set(process->isolation.clone.flags, NEWNS)) { 6811671St.nateldemoura@f5.com return; 6821671St.nateldemoura@f5.com } 6831671St.nateldemoura@f5.com #endif 6841671St.nateldemoura@f5.com 6851579St.nateldemoura@f5.com nxt_debug(task, "unmount all (%s)", process->name); 6861579St.nateldemoura@f5.com 6871585St.nateldemoura@f5.com automount = &process->isolation.automount; 6881579St.nateldemoura@f5.com mounts = process->isolation.mounts; 6891579St.nateldemoura@f5.com n = mounts->nelts; 6901579St.nateldemoura@f5.com mnt = mounts->elts; 6911579St.nateldemoura@f5.com 6921671St.nateldemoura@f5.com while (n > 0) { 6931671St.nateldemoura@f5.com n--; 6941671St.nateldemoura@f5.com 6951673St.nateldemoura@f5.com if (mnt[n].deps && !automount->language_deps) { 6961585St.nateldemoura@f5.com continue; 6971585St.nateldemoura@f5.com } 6981585St.nateldemoura@f5.com 6991671St.nateldemoura@f5.com nxt_fs_unmount(mnt[n].dst); 7001579St.nateldemoura@f5.com } 7011579St.nateldemoura@f5.com } 7021579St.nateldemoura@f5.com 7031579St.nateldemoura@f5.com 7041579St.nateldemoura@f5.com nxt_int_t 7051579St.nateldemoura@f5.com nxt_isolation_prepare_rootfs(nxt_task_t *task, nxt_process_t *process) 7061579St.nateldemoura@f5.com { 7071585St.nateldemoura@f5.com size_t i, n; 7081585St.nateldemoura@f5.com nxt_int_t ret; 7091585St.nateldemoura@f5.com struct stat st; 7101585St.nateldemoura@f5.com nxt_array_t *mounts; 7111585St.nateldemoura@f5.com const u_char *dst; 7121585St.nateldemoura@f5.com nxt_fs_mount_t *mnt; 7131585St.nateldemoura@f5.com nxt_process_automount_t *automount; 7141579St.nateldemoura@f5.com 7151585St.nateldemoura@f5.com automount = &process->isolation.automount; 7161579St.nateldemoura@f5.com mounts = process->isolation.mounts; 7171579St.nateldemoura@f5.com 7181579St.nateldemoura@f5.com n = mounts->nelts; 7191579St.nateldemoura@f5.com mnt = mounts->elts; 7201579St.nateldemoura@f5.com 7211579St.nateldemoura@f5.com for (i = 0; i < n; i++) { 7221579St.nateldemoura@f5.com dst = mnt[i].dst; 7231579St.nateldemoura@f5.com 7241673St.nateldemoura@f5.com if (mnt[i].deps && !automount->language_deps) { 7251585St.nateldemoura@f5.com continue; 7261585St.nateldemoura@f5.com } 7271585St.nateldemoura@f5.com 7281673St.nateldemoura@f5.com if (nxt_slow_path(mnt[i].type == NXT_FS_BIND 7291579St.nateldemoura@f5.com && stat((const char *) mnt[i].src, &st) != 0)) 7301579St.nateldemoura@f5.com { 7311579St.nateldemoura@f5.com nxt_log(task, NXT_LOG_WARN, "host path not found: %s", mnt[i].src); 7321579St.nateldemoura@f5.com continue; 7331579St.nateldemoura@f5.com } 7341579St.nateldemoura@f5.com 7351579St.nateldemoura@f5.com ret = nxt_fs_mkdir_all(dst, S_IRWXU | S_IRWXG | S_IRWXO); 7361579St.nateldemoura@f5.com if (nxt_slow_path(ret != NXT_OK)) { 7371579St.nateldemoura@f5.com nxt_alert(task, "mkdir(%s) %E", dst, nxt_errno); 7381579St.nateldemoura@f5.com goto undo; 7391579St.nateldemoura@f5.com } 7401579St.nateldemoura@f5.com 7411579St.nateldemoura@f5.com ret = nxt_fs_mount(task, &mnt[i]); 7421579St.nateldemoura@f5.com if (nxt_slow_path(ret != NXT_OK)) { 7431579St.nateldemoura@f5.com goto undo; 7441579St.nateldemoura@f5.com } 7451579St.nateldemoura@f5.com } 7461579St.nateldemoura@f5.com 7471579St.nateldemoura@f5.com return NXT_OK; 7481579St.nateldemoura@f5.com 7491579St.nateldemoura@f5.com undo: 7501579St.nateldemoura@f5.com 7511579St.nateldemoura@f5.com n = i + 1; 7521579St.nateldemoura@f5.com 7531579St.nateldemoura@f5.com for (i = 0; i < n; i++) { 7541579St.nateldemoura@f5.com nxt_fs_unmount(mnt[i].dst); 7551579St.nateldemoura@f5.com } 7561579St.nateldemoura@f5.com 7571579St.nateldemoura@f5.com return NXT_ERROR; 7581579St.nateldemoura@f5.com } 7591579St.nateldemoura@f5.com 7601579St.nateldemoura@f5.com 7611579St.nateldemoura@f5.com #if (NXT_HAVE_PIVOT_ROOT) && (NXT_HAVE_CLONE_NEWNS) 7621579St.nateldemoura@f5.com 7631579St.nateldemoura@f5.com nxt_int_t 7641579St.nateldemoura@f5.com nxt_isolation_change_root(nxt_task_t *task, nxt_process_t *process) 7651579St.nateldemoura@f5.com { 7661579St.nateldemoura@f5.com char *rootfs; 7671579St.nateldemoura@f5.com nxt_int_t ret; 7681579St.nateldemoura@f5.com 7691579St.nateldemoura@f5.com rootfs = (char *) process->isolation.rootfs; 7701579St.nateldemoura@f5.com 7711579St.nateldemoura@f5.com nxt_debug(task, "change root: %s", rootfs); 7721579St.nateldemoura@f5.com 7731595St.nateldemoura@f5.com if (nxt_is_clone_flag_set(process->isolation.clone.flags, NEWNS)) { 7741579St.nateldemoura@f5.com ret = nxt_isolation_pivot_root(task, rootfs); 7751579St.nateldemoura@f5.com 7761579St.nateldemoura@f5.com } else { 7771579St.nateldemoura@f5.com ret = nxt_isolation_chroot(task, rootfs); 7781579St.nateldemoura@f5.com } 7791579St.nateldemoura@f5.com 7801579St.nateldemoura@f5.com if (nxt_fast_path(ret == NXT_OK)) { 7811579St.nateldemoura@f5.com if (nxt_slow_path(chdir("/") < 0)) { 7821579St.nateldemoura@f5.com nxt_alert(task, "chdir(\"/\") %E", nxt_errno); 7831579St.nateldemoura@f5.com return NXT_ERROR; 7841579St.nateldemoura@f5.com } 7851579St.nateldemoura@f5.com } 7861579St.nateldemoura@f5.com 7871579St.nateldemoura@f5.com return ret; 7881579St.nateldemoura@f5.com } 7891579St.nateldemoura@f5.com 7901579St.nateldemoura@f5.com 7911579St.nateldemoura@f5.com /* 7921579St.nateldemoura@f5.com * pivot_root(2) can only be safely used with containers, otherwise it can 7931579St.nateldemoura@f5.com * umount(2) the global root filesystem and screw up the machine. 7941579St.nateldemoura@f5.com */ 7951579St.nateldemoura@f5.com 7961579St.nateldemoura@f5.com static nxt_int_t 7971579St.nateldemoura@f5.com nxt_isolation_pivot_root(nxt_task_t *task, const char *path) 7981579St.nateldemoura@f5.com { 7991579St.nateldemoura@f5.com /* 8001579St.nateldemoura@f5.com * This implementation makes use of a kernel trick that works for ages 8011579St.nateldemoura@f5.com * and now documented in Linux kernel 5. 8021579St.nateldemoura@f5.com * https://lore.kernel.org/linux-man/87r24piwhm.fsf@x220.int.ebiederm.org/T/ 8031579St.nateldemoura@f5.com */ 8041579St.nateldemoura@f5.com 8051579St.nateldemoura@f5.com if (nxt_slow_path(mount("", "/", "", MS_SLAVE|MS_REC, "") != 0)) { 8061602Sartem.konev@nginx.com nxt_alert(task, "mount(\"/\", MS_SLAVE|MS_REC) failed: %E", nxt_errno); 8071579St.nateldemoura@f5.com return NXT_ERROR; 8081579St.nateldemoura@f5.com } 8091579St.nateldemoura@f5.com 8101579St.nateldemoura@f5.com if (nxt_slow_path(nxt_isolation_make_private_mount(task, path) != NXT_OK)) { 8111579St.nateldemoura@f5.com return NXT_ERROR; 8121579St.nateldemoura@f5.com } 8131579St.nateldemoura@f5.com 8141579St.nateldemoura@f5.com if (nxt_slow_path(mount(path, path, "bind", MS_BIND|MS_REC, "") != 0)) { 8151579St.nateldemoura@f5.com nxt_alert(task, "error bind mounting rootfs %E", nxt_errno); 8161579St.nateldemoura@f5.com return NXT_ERROR; 8171579St.nateldemoura@f5.com } 8181579St.nateldemoura@f5.com 8191579St.nateldemoura@f5.com if (nxt_slow_path(chdir(path) != 0)) { 8201579St.nateldemoura@f5.com nxt_alert(task, "failed to chdir(%s) %E", path, nxt_errno); 8211579St.nateldemoura@f5.com return NXT_ERROR; 8221579St.nateldemoura@f5.com } 8231579St.nateldemoura@f5.com 8241579St.nateldemoura@f5.com if (nxt_slow_path(nxt_pivot_root(".", ".") != 0)) { 8251579St.nateldemoura@f5.com nxt_alert(task, "failed to pivot_root %E", nxt_errno); 8261579St.nateldemoura@f5.com return NXT_ERROR; 8271579St.nateldemoura@f5.com } 8281579St.nateldemoura@f5.com 8291579St.nateldemoura@f5.com /* 8301602Sartem.konev@nginx.com * Demote the oldroot mount to avoid unmounts getting propagated to 8311602Sartem.konev@nginx.com * the host. 8321579St.nateldemoura@f5.com */ 8331579St.nateldemoura@f5.com if (nxt_slow_path(mount("", ".", "", MS_SLAVE | MS_REC, NULL) != 0)) { 8341579St.nateldemoura@f5.com nxt_alert(task, "failed to bind mount rootfs %E", nxt_errno); 8351579St.nateldemoura@f5.com return NXT_ERROR; 8361579St.nateldemoura@f5.com } 8371579St.nateldemoura@f5.com 8381579St.nateldemoura@f5.com if (nxt_slow_path(umount2(".", MNT_DETACH) != 0)) { 8391579St.nateldemoura@f5.com nxt_alert(task, "failed to umount old root directory %E", nxt_errno); 8401579St.nateldemoura@f5.com return NXT_ERROR; 8411579St.nateldemoura@f5.com } 8421579St.nateldemoura@f5.com 8431579St.nateldemoura@f5.com return NXT_OK; 8441579St.nateldemoura@f5.com } 8451579St.nateldemoura@f5.com 8461579St.nateldemoura@f5.com 8471579St.nateldemoura@f5.com static nxt_int_t 8481579St.nateldemoura@f5.com nxt_isolation_make_private_mount(nxt_task_t *task, const char *rootfs) 8491579St.nateldemoura@f5.com { 8501579St.nateldemoura@f5.com char *parent_mnt; 8511579St.nateldemoura@f5.com FILE *procfile; 8521579St.nateldemoura@f5.com u_char **mounts; 8531579St.nateldemoura@f5.com size_t len; 8541579St.nateldemoura@f5.com uint8_t *shared; 8551579St.nateldemoura@f5.com nxt_int_t ret, index, nmounts; 8561579St.nateldemoura@f5.com struct mntent *ent; 8571579St.nateldemoura@f5.com 8581579St.nateldemoura@f5.com static const char *mount_path = "/proc/self/mounts"; 8591579St.nateldemoura@f5.com 8601579St.nateldemoura@f5.com ret = NXT_ERROR; 8611579St.nateldemoura@f5.com ent = NULL; 8621579St.nateldemoura@f5.com shared = NULL; 8631579St.nateldemoura@f5.com procfile = NULL; 8641579St.nateldemoura@f5.com parent_mnt = NULL; 8651579St.nateldemoura@f5.com 8661579St.nateldemoura@f5.com nmounts = 256; 8671579St.nateldemoura@f5.com 8681579St.nateldemoura@f5.com mounts = nxt_malloc(nmounts * sizeof(uintptr_t)); 8691579St.nateldemoura@f5.com if (nxt_slow_path(mounts == NULL)) { 8701579St.nateldemoura@f5.com goto fail; 8711579St.nateldemoura@f5.com } 8721579St.nateldemoura@f5.com 8731579St.nateldemoura@f5.com shared = nxt_malloc(nmounts); 8741579St.nateldemoura@f5.com if (nxt_slow_path(shared == NULL)) { 8751579St.nateldemoura@f5.com goto fail; 8761579St.nateldemoura@f5.com } 8771579St.nateldemoura@f5.com 8781579St.nateldemoura@f5.com procfile = setmntent(mount_path, "r"); 8791579St.nateldemoura@f5.com if (nxt_slow_path(procfile == NULL)) { 8801579St.nateldemoura@f5.com nxt_alert(task, "failed to open %s %E", mount_path, nxt_errno); 8811579St.nateldemoura@f5.com 8821579St.nateldemoura@f5.com goto fail; 8831579St.nateldemoura@f5.com } 8841579St.nateldemoura@f5.com 8851579St.nateldemoura@f5.com index = 0; 8861579St.nateldemoura@f5.com 8871579St.nateldemoura@f5.com again: 8881579St.nateldemoura@f5.com 8891579St.nateldemoura@f5.com for ( ; index < nmounts; index++) { 8901579St.nateldemoura@f5.com ent = getmntent(procfile); 8911579St.nateldemoura@f5.com if (ent == NULL) { 8921579St.nateldemoura@f5.com nmounts = index; 8931579St.nateldemoura@f5.com break; 8941579St.nateldemoura@f5.com } 8951579St.nateldemoura@f5.com 8961579St.nateldemoura@f5.com mounts[index] = (u_char *) strdup(ent->mnt_dir); 8971579St.nateldemoura@f5.com shared[index] = hasmntopt(ent, "shared") != NULL; 8981579St.nateldemoura@f5.com } 8991579St.nateldemoura@f5.com 9001579St.nateldemoura@f5.com if (ent != NULL) { 9011579St.nateldemoura@f5.com /* there are still entries to be read */ 9021579St.nateldemoura@f5.com 9031579St.nateldemoura@f5.com nmounts *= 2; 9041579St.nateldemoura@f5.com mounts = nxt_realloc(mounts, nmounts); 9051579St.nateldemoura@f5.com if (nxt_slow_path(mounts == NULL)) { 9061579St.nateldemoura@f5.com goto fail; 9071579St.nateldemoura@f5.com } 9081579St.nateldemoura@f5.com 9091579St.nateldemoura@f5.com shared = nxt_realloc(shared, nmounts); 9101579St.nateldemoura@f5.com if (nxt_slow_path(shared == NULL)) { 9111579St.nateldemoura@f5.com goto fail; 9121579St.nateldemoura@f5.com } 9131579St.nateldemoura@f5.com 9141579St.nateldemoura@f5.com goto again; 9151579St.nateldemoura@f5.com } 9161579St.nateldemoura@f5.com 9171579St.nateldemoura@f5.com for (index = 0; index < nmounts; index++) { 9181579St.nateldemoura@f5.com if (nxt_strcmp(mounts[index], rootfs) == 0) { 9191579St.nateldemoura@f5.com parent_mnt = (char *) rootfs; 9201579St.nateldemoura@f5.com break; 9211579St.nateldemoura@f5.com } 9221579St.nateldemoura@f5.com } 9231579St.nateldemoura@f5.com 9241579St.nateldemoura@f5.com if (parent_mnt == NULL) { 9251579St.nateldemoura@f5.com len = nxt_strlen(rootfs); 9261579St.nateldemoura@f5.com 9271579St.nateldemoura@f5.com parent_mnt = nxt_malloc(len + 1); 9281579St.nateldemoura@f5.com if (parent_mnt == NULL) { 9291579St.nateldemoura@f5.com goto fail; 9301579St.nateldemoura@f5.com } 9311579St.nateldemoura@f5.com 9321579St.nateldemoura@f5.com nxt_memcpy(parent_mnt, rootfs, len); 9331579St.nateldemoura@f5.com parent_mnt[len] = '\0'; 9341579St.nateldemoura@f5.com 9351579St.nateldemoura@f5.com if (parent_mnt[len - 1] == '/') { 9361579St.nateldemoura@f5.com parent_mnt[len - 1] = '\0'; 9371579St.nateldemoura@f5.com len--; 9381579St.nateldemoura@f5.com } 9391579St.nateldemoura@f5.com 9401579St.nateldemoura@f5.com for ( ;; ) { 9411579St.nateldemoura@f5.com for (index = 0; index < nmounts; index++) { 9421579St.nateldemoura@f5.com if (nxt_strcmp(mounts[index], parent_mnt) == 0) { 9431579St.nateldemoura@f5.com goto found; 9441579St.nateldemoura@f5.com } 9451579St.nateldemoura@f5.com } 9461579St.nateldemoura@f5.com 9471579St.nateldemoura@f5.com if (len == 1 && parent_mnt[0] == '/') { 9481579St.nateldemoura@f5.com nxt_alert(task, "parent mount not found"); 9491579St.nateldemoura@f5.com goto fail; 9501579St.nateldemoura@f5.com } 9511579St.nateldemoura@f5.com 9521579St.nateldemoura@f5.com /* parent dir */ 9531579St.nateldemoura@f5.com while (parent_mnt[len - 1] != '/' && len > 0) { 9541579St.nateldemoura@f5.com len--; 9551579St.nateldemoura@f5.com } 9561579St.nateldemoura@f5.com 9571579St.nateldemoura@f5.com if (nxt_slow_path(len == 0)) { 9581579St.nateldemoura@f5.com nxt_alert(task, "parent mount not found"); 9591579St.nateldemoura@f5.com goto fail; 9601579St.nateldemoura@f5.com } 9611579St.nateldemoura@f5.com 9621579St.nateldemoura@f5.com if (len == 1) { 9631579St.nateldemoura@f5.com parent_mnt[len] = '\0'; /* / */ 9641579St.nateldemoura@f5.com } else { 9651579St.nateldemoura@f5.com parent_mnt[len - 1] = '\0'; /* /<path> */ 9661579St.nateldemoura@f5.com } 9671579St.nateldemoura@f5.com } 9681579St.nateldemoura@f5.com } 9691579St.nateldemoura@f5.com 9701579St.nateldemoura@f5.com found: 9711579St.nateldemoura@f5.com 9721579St.nateldemoura@f5.com if (shared[index]) { 9731579St.nateldemoura@f5.com if (nxt_slow_path(mount("", parent_mnt, "", MS_PRIVATE, "") != 0)) { 9741579St.nateldemoura@f5.com nxt_alert(task, "mount(\"\", \"%s\", MS_PRIVATE) %E", parent_mnt, 9751579St.nateldemoura@f5.com nxt_errno); 9761579St.nateldemoura@f5.com 9771579St.nateldemoura@f5.com goto fail; 9781579St.nateldemoura@f5.com } 9791579St.nateldemoura@f5.com } 9801579St.nateldemoura@f5.com 9811579St.nateldemoura@f5.com ret = NXT_OK; 9821579St.nateldemoura@f5.com 9831579St.nateldemoura@f5.com fail: 9841579St.nateldemoura@f5.com 9851579St.nateldemoura@f5.com if (procfile != NULL) { 9861579St.nateldemoura@f5.com endmntent(procfile); 9871579St.nateldemoura@f5.com } 9881579St.nateldemoura@f5.com 9891579St.nateldemoura@f5.com if (mounts != NULL) { 9901579St.nateldemoura@f5.com for (index = 0; index < nmounts; index++) { 9911579St.nateldemoura@f5.com nxt_free(mounts[index]); 9921579St.nateldemoura@f5.com } 9931579St.nateldemoura@f5.com 9941579St.nateldemoura@f5.com nxt_free(mounts); 9951579St.nateldemoura@f5.com } 9961579St.nateldemoura@f5.com 9971579St.nateldemoura@f5.com if (shared != NULL) { 9981579St.nateldemoura@f5.com nxt_free(shared); 9991579St.nateldemoura@f5.com } 10001579St.nateldemoura@f5.com 10011579St.nateldemoura@f5.com if (parent_mnt != NULL && parent_mnt != rootfs) { 10021579St.nateldemoura@f5.com nxt_free(parent_mnt); 10031579St.nateldemoura@f5.com } 10041579St.nateldemoura@f5.com 10051579St.nateldemoura@f5.com return ret; 10061579St.nateldemoura@f5.com } 10071579St.nateldemoura@f5.com 10081579St.nateldemoura@f5.com 10091579St.nateldemoura@f5.com nxt_inline int 10101579St.nateldemoura@f5.com nxt_pivot_root(const char *new_root, const char *old_root) 10111579St.nateldemoura@f5.com { 10121579St.nateldemoura@f5.com return syscall(__NR_pivot_root, new_root, old_root); 10131579St.nateldemoura@f5.com } 10141579St.nateldemoura@f5.com 10151579St.nateldemoura@f5.com 10161579St.nateldemoura@f5.com #else /* !(NXT_HAVE_PIVOT_ROOT) || !(NXT_HAVE_CLONE_NEWNS) */ 10171579St.nateldemoura@f5.com 10181579St.nateldemoura@f5.com 10191579St.nateldemoura@f5.com nxt_int_t 10201579St.nateldemoura@f5.com nxt_isolation_change_root(nxt_task_t *task, nxt_process_t *process) 10211579St.nateldemoura@f5.com { 10221579St.nateldemoura@f5.com char *rootfs; 10231579St.nateldemoura@f5.com 10241579St.nateldemoura@f5.com rootfs = (char *) process->isolation.rootfs; 10251579St.nateldemoura@f5.com 10261579St.nateldemoura@f5.com nxt_debug(task, "change root: %s", rootfs); 10271579St.nateldemoura@f5.com 10281579St.nateldemoura@f5.com if (nxt_fast_path(nxt_isolation_chroot(task, rootfs) == NXT_OK)) { 10291579St.nateldemoura@f5.com if (nxt_slow_path(chdir("/") < 0)) { 10301579St.nateldemoura@f5.com nxt_alert(task, "chdir(\"/\") %E", nxt_errno); 10311579St.nateldemoura@f5.com return NXT_ERROR; 10321579St.nateldemoura@f5.com } 10331579St.nateldemoura@f5.com 10341579St.nateldemoura@f5.com return NXT_OK; 10351579St.nateldemoura@f5.com } 10361579St.nateldemoura@f5.com 10371579St.nateldemoura@f5.com return NXT_ERROR; 10381579St.nateldemoura@f5.com } 10391579St.nateldemoura@f5.com 10401579St.nateldemoura@f5.com #endif 10411579St.nateldemoura@f5.com 10421579St.nateldemoura@f5.com 10431579St.nateldemoura@f5.com static nxt_int_t 10441579St.nateldemoura@f5.com nxt_isolation_chroot(nxt_task_t *task, const char *path) 10451579St.nateldemoura@f5.com { 10461579St.nateldemoura@f5.com if (nxt_slow_path(chroot(path) < 0)) { 10471579St.nateldemoura@f5.com nxt_alert(task, "chroot(%s) %E", path, nxt_errno); 10481579St.nateldemoura@f5.com return NXT_ERROR; 10491579St.nateldemoura@f5.com } 10501579St.nateldemoura@f5.com 10511579St.nateldemoura@f5.com return NXT_OK; 10521579St.nateldemoura@f5.com } 10531579St.nateldemoura@f5.com 10541579St.nateldemoura@f5.com #endif /* NXT_HAVE_ISOLATION_ROOTFS */ 10551579St.nateldemoura@f5.com 10561579St.nateldemoura@f5.com 10571579St.nateldemoura@f5.com #if (NXT_HAVE_PR_SET_NO_NEW_PRIVS) 10581579St.nateldemoura@f5.com 10591579St.nateldemoura@f5.com static nxt_int_t 10601579St.nateldemoura@f5.com nxt_isolation_set_new_privs(nxt_task_t *task, nxt_conf_value_t *isolation, 10611579St.nateldemoura@f5.com nxt_process_t *process) 10621579St.nateldemoura@f5.com { 10631579St.nateldemoura@f5.com nxt_conf_value_t *obj; 10641579St.nateldemoura@f5.com 10651579St.nateldemoura@f5.com static nxt_str_t new_privs_name = nxt_string("new_privs"); 10661579St.nateldemoura@f5.com 10671579St.nateldemoura@f5.com obj = nxt_conf_get_object_member(isolation, &new_privs_name, NULL); 10681579St.nateldemoura@f5.com if (obj != NULL) { 10691579St.nateldemoura@f5.com process->isolation.new_privs = nxt_conf_get_boolean(obj); 10701579St.nateldemoura@f5.com } 10711579St.nateldemoura@f5.com 10721579St.nateldemoura@f5.com return NXT_OK; 10731579St.nateldemoura@f5.com } 10741579St.nateldemoura@f5.com 10751579St.nateldemoura@f5.com #endif 1076