From 5ffd88ad7c682f4bc60702d8829d1534aafb09e8 Mon Sep 17 00:00:00 2001 From: Tiago Natel de Moura Date: Thu, 29 Oct 2020 14:24:38 +0000 Subject: Isolation: correctly unmount non-dependent paths first. When mount points reside within other mount points, this patch sorts them by path length and then unmounts then in an order reverse to their mounting. This results in independent paths being unmounted first. This fixes an issue in buildbots where dependent paths failed to unmount, leading to the build script removing system-wide language libraries. --- src/nxt_isolation.c | 40 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 36 insertions(+), 4 deletions(-) (limited to 'src/nxt_isolation.c') diff --git a/src/nxt_isolation.c b/src/nxt_isolation.c index ac7a37e8..03160de3 100644 --- a/src/nxt_isolation.c +++ b/src/nxt_isolation.c @@ -41,6 +41,8 @@ static nxt_int_t nxt_isolation_set_mounts(nxt_task_t *task, nxt_process_t *process, nxt_str_t *app_type); static nxt_int_t nxt_isolation_set_lang_mounts(nxt_task_t *task, nxt_process_t *process, nxt_array_t *syspaths); +static int nxt_cdecl nxt_isolation_mount_compare(const void *v1, + const void *v2); static void nxt_isolation_unmount_all(nxt_task_t *task, nxt_process_t *process); #if (NXT_HAVE_PIVOT_ROOT) && (NXT_HAVE_CLONE_NEWNS) @@ -607,20 +609,48 @@ nxt_isolation_set_lang_mounts(nxt_task_t *task, nxt_process_t *process, } #endif + qsort(mounts->elts, mounts->nelts, sizeof(nxt_fs_mount_t), + nxt_isolation_mount_compare); + process->isolation.mounts = mounts; return NXT_OK; } +static int nxt_cdecl +nxt_isolation_mount_compare(const void *v1, const void *v2) +{ + const nxt_fs_mount_t *mnt1, *mnt2; + + mnt1 = v1; + mnt2 = v2; + + return nxt_strlen(mnt1->src) > nxt_strlen(mnt2->src); +} + + void nxt_isolation_unmount_all(nxt_task_t *task, nxt_process_t *process) { - size_t i, n; + size_t n; nxt_array_t *mounts; + nxt_runtime_t *rt; nxt_fs_mount_t *mnt; nxt_process_automount_t *automount; + rt = task->thread->runtime; + + if (!rt->capabilities.setid) { + return; + } + +#if (NXT_HAVE_CLONE_NEWNS) + if (nxt_is_clone_flag_set(process->isolation.clone.flags, NEWNS)) { + return; + } +#endif + nxt_debug(task, "unmount all (%s)", process->name); automount = &process->isolation.automount; @@ -628,12 +658,14 @@ nxt_isolation_unmount_all(nxt_task_t *task, nxt_process_t *process) n = mounts->nelts; mnt = mounts->elts; - for (i = 0; i < n; i++) { - if (mnt[i].builtin && !automount->language_deps) { + while (n > 0) { + n--; + + if (mnt[n].builtin && !automount->language_deps) { continue; } - nxt_fs_unmount(mnt[i].dst); + nxt_fs_unmount(mnt[n].dst); } } -- cgit From 0390cb3a61051dd93e206d50591aff5759cf42fc Mon Sep 17 00:00:00 2001 From: Tiago Natel de Moura Date: Thu, 29 Oct 2020 20:30:53 +0000 Subject: Isolation: mounting of procfs by default when using "rootfs". --- src/nxt_isolation.c | 86 ++++++++++++++++++++++++++++++----------------------- 1 file changed, 49 insertions(+), 37 deletions(-) (limited to 'src/nxt_isolation.c') diff --git a/src/nxt_isolation.c b/src/nxt_isolation.c index 03160de3..e0f169aa 100644 --- a/src/nxt_isolation.c +++ b/src/nxt_isolation.c @@ -87,15 +87,6 @@ nxt_isolation_main_prefork(nxt_task_t *task, nxt_process_t *process, } #endif -#if (NXT_HAVE_ISOLATION_ROOTFS) - if (process->isolation.rootfs != NULL) { - ret = nxt_isolation_set_mounts(task, process, &app_conf->type); - if (nxt_slow_path(ret != NXT_OK)) { - return ret; - } - } -#endif - if (cap_setid) { ret = nxt_process_creds_set(task, process, &app_conf->user, &app_conf->group); @@ -126,6 +117,29 @@ nxt_isolation_main_prefork(nxt_task_t *task, nxt_process_t *process, } } +#if (NXT_HAVE_ISOLATION_ROOTFS) + if (process->isolation.rootfs != NULL) { + nxt_int_t has_mnt; + + ret = nxt_isolation_set_mounts(task, process, &app_conf->type); + if (nxt_slow_path(ret != NXT_OK)) { + return ret; + } + + has_mnt = 0; + +#if (NXT_HAVE_CLONE_NEWNS) + has_mnt = nxt_is_clone_flag_set(process->isolation.clone.flags, NEWNS); +#endif + + if (process->user_cred->uid == 0 && !has_mnt) { + nxt_log(task, NXT_LOG_WARN, + "setting user \"root\" with \"rootfs\" is unsafe without " + "\"mount\" namespace isolation"); + } + } +#endif + #if (NXT_HAVE_CLONE_NEWUSER) ret = nxt_isolation_vldt_creds(task, process); if (nxt_slow_path(ret != NXT_OK)) { @@ -568,10 +582,13 @@ nxt_isolation_set_lang_mounts(nxt_task_t *task, nxt_process_t *process, } mnt->src = (u_char *) "tmpfs"; - mnt->fstype = (u_char *) "tmpfs"; - mnt->flags = NXT_MS_NOSUID | NXT_MS_NODEV | NXT_MS_NOEXEC | NXT_MS_RELATIME; + mnt->name = (u_char *) "tmpfs"; + mnt->type = NXT_FS_TMP; + mnt->flags = (NXT_FS_FLAGS_NOSUID | NXT_FS_FLAGS_NODEV + | NXT_FS_FLAGS_NOEXEC); mnt->data = (u_char *) "size=1m,mode=777"; mnt->builtin = 1; + mnt->deps = 0; mnt->dst = nxt_mp_nget(mp, rootfs_len + nxt_length("/tmp") + 1); if (nxt_slow_path(mnt->dst == NULL)) { @@ -582,32 +599,27 @@ nxt_isolation_set_lang_mounts(nxt_task_t *task, nxt_process_t *process, p = nxt_cpymem(p, "/tmp", 4); *p = '\0'; -#if (NXT_HAVE_CLONE_NEWPID) && (NXT_HAVE_CLONE_NEWNS) - - if (nxt_is_clone_flag_set(process->isolation.clone.flags, NEWPID) - && nxt_is_clone_flag_set(process->isolation.clone.flags, NEWNS)) - { - mnt = nxt_array_add(mounts); - if (nxt_slow_path(mnt == NULL)) { - return NXT_ERROR; - } - - mnt->fstype = (u_char *) "proc"; - mnt->src = (u_char *) "proc"; + mnt = nxt_array_add(mounts); + if (nxt_slow_path(mnt == NULL)) { + return NXT_ERROR; + } - mnt->dst = nxt_mp_nget(mp, rootfs_len + nxt_length("/proc") + 1); - if (nxt_slow_path(mnt->dst == NULL)) { - return NXT_ERROR; - } + mnt->name = (u_char *) "proc"; + mnt->type = NXT_FS_PROC; + mnt->src = (u_char *) "none"; + mnt->dst = nxt_mp_nget(mp, rootfs_len + nxt_length("/proc") + 1); + if (nxt_slow_path(mnt->dst == NULL)) { + return NXT_ERROR; + } - p = nxt_cpymem(mnt->dst, rootfs, rootfs_len); - p = nxt_cpymem(p, "/proc", 5); - *p = '\0'; + p = nxt_cpymem(mnt->dst, rootfs, rootfs_len); + p = nxt_cpymem(p, "/proc", 5); + *p = '\0'; - mnt->data = (u_char *) ""; - mnt->flags = 0; - } -#endif + mnt->data = (u_char *) ""; + mnt->flags = NXT_FS_FLAGS_NOEXEC | NXT_FS_FLAGS_NOSUID; + mnt->builtin = 1; + mnt->deps = 0; qsort(mounts->elts, mounts->nelts, sizeof(nxt_fs_mount_t), nxt_isolation_mount_compare); @@ -661,7 +673,7 @@ nxt_isolation_unmount_all(nxt_task_t *task, nxt_process_t *process) while (n > 0) { n--; - if (mnt[n].builtin && !automount->language_deps) { + if (mnt[n].deps && !automount->language_deps) { continue; } @@ -690,11 +702,11 @@ nxt_isolation_prepare_rootfs(nxt_task_t *task, nxt_process_t *process) for (i = 0; i < n; i++) { dst = mnt[i].dst; - if (mnt[i].builtin && !automount->language_deps) { + if (mnt[i].deps && !automount->language_deps) { continue; } - if (nxt_slow_path(nxt_memcmp(mnt[i].fstype, "bind", 4) == 0 + if (nxt_slow_path(mnt[i].type == NXT_FS_BIND && stat((const char *) mnt[i].src, &st) != 0)) { nxt_log(task, NXT_LOG_WARN, "host path not found: %s", mnt[i].src); -- cgit From 3837d28f9b7c5d0840d2e4b26f4867b66838d31b Mon Sep 17 00:00:00 2001 From: Tiago Natel de Moura Date: Fri, 13 Nov 2020 10:48:32 +0000 Subject: Isolation: added option to disable tmpfs mount. Now users can disable the default tmpfs mount point in the rootfs. { "isolation": { "automount": { "tmpfs": false } } } --- src/nxt_isolation.c | 48 +++++++++++++++++++++++++++++------------------- 1 file changed, 29 insertions(+), 19 deletions(-) (limited to 'src/nxt_isolation.c') diff --git a/src/nxt_isolation.c b/src/nxt_isolation.c index e0f169aa..f0ef625f 100644 --- a/src/nxt_isolation.c +++ b/src/nxt_isolation.c @@ -484,10 +484,12 @@ nxt_isolation_set_automount(nxt_task_t *task, nxt_conf_value_t *isolation, static nxt_str_t automount_name = nxt_string("automount"); static nxt_str_t langdeps_name = nxt_string("language_deps"); + static nxt_str_t tmp_name = nxt_string("tmpfs"); automount = &process->isolation.automount; automount->language_deps = 1; + automount->tmpfs = 1; conf = nxt_conf_get_object_member(isolation, &automount_name, NULL); if (conf != NULL) { @@ -495,6 +497,11 @@ nxt_isolation_set_automount(nxt_task_t *task, nxt_conf_value_t *isolation, if (value != NULL) { automount->language_deps = nxt_conf_get_boolean(value); } + + value = nxt_conf_get_object_member(conf, &tmp_name, NULL); + if (value != NULL) { + automount->tmpfs = nxt_conf_get_boolean(value); + } } return NXT_OK; @@ -576,29 +583,32 @@ nxt_isolation_set_lang_mounts(nxt_task_t *task, nxt_process_t *process, *p = '\0'; } - mnt = nxt_array_add(mounts); - if (nxt_slow_path(mnt == NULL)) { - return NXT_ERROR; - } + if (process->isolation.automount.tmpfs) { + mnt = nxt_array_add(mounts); + if (nxt_slow_path(mnt == NULL)) { + return NXT_ERROR; + } - mnt->src = (u_char *) "tmpfs"; - mnt->name = (u_char *) "tmpfs"; - mnt->type = NXT_FS_TMP; - mnt->flags = (NXT_FS_FLAGS_NOSUID | NXT_FS_FLAGS_NODEV - | NXT_FS_FLAGS_NOEXEC); - mnt->data = (u_char *) "size=1m,mode=777"; - mnt->builtin = 1; - mnt->deps = 0; + mnt->src = (u_char *) "tmpfs"; + mnt->name = (u_char *) "tmpfs"; + mnt->type = NXT_FS_TMP; + mnt->flags = (NXT_FS_FLAGS_NOSUID + | NXT_FS_FLAGS_NODEV + | NXT_FS_FLAGS_NOEXEC); + mnt->data = (u_char *) "size=1m,mode=777"; + mnt->builtin = 1; + mnt->deps = 0; + + mnt->dst = nxt_mp_nget(mp, rootfs_len + nxt_length("/tmp") + 1); + if (nxt_slow_path(mnt->dst == NULL)) { + return NXT_ERROR; + } - mnt->dst = nxt_mp_nget(mp, rootfs_len + nxt_length("/tmp") + 1); - if (nxt_slow_path(mnt->dst == NULL)) { - return NXT_ERROR; + p = nxt_cpymem(mnt->dst, rootfs, rootfs_len); + p = nxt_cpymem(p, "/tmp", 4); + *p = '\0'; } - p = nxt_cpymem(mnt->dst, rootfs, rootfs_len); - p = nxt_cpymem(p, "/tmp", 4); - *p = '\0'; - mnt = nxt_array_add(mounts); if (nxt_slow_path(mnt == NULL)) { return NXT_ERROR; -- cgit From e7d66acda726490fb7b8da03f0d4788857918d5a Mon Sep 17 00:00:00 2001 From: Tiago Natel de Moura Date: Mon, 16 Nov 2020 17:56:12 +0000 Subject: Isolation: added option to disable "procfs" mount. Now users can disable the default procfs mount point in the rootfs. { "isolation": { "automount": { "procfs": false } } } --- src/nxt_isolation.c | 45 +++++++++++++++++++++++++++------------------ 1 file changed, 27 insertions(+), 18 deletions(-) (limited to 'src/nxt_isolation.c') diff --git a/src/nxt_isolation.c b/src/nxt_isolation.c index f0ef625f..1e6323bc 100644 --- a/src/nxt_isolation.c +++ b/src/nxt_isolation.c @@ -485,11 +485,13 @@ nxt_isolation_set_automount(nxt_task_t *task, nxt_conf_value_t *isolation, static nxt_str_t automount_name = nxt_string("automount"); static nxt_str_t langdeps_name = nxt_string("language_deps"); static nxt_str_t tmp_name = nxt_string("tmpfs"); + static nxt_str_t proc_name = nxt_string("procfs"); automount = &process->isolation.automount; automount->language_deps = 1; automount->tmpfs = 1; + automount->procfs = 1; conf = nxt_conf_get_object_member(isolation, &automount_name, NULL); if (conf != NULL) { @@ -502,6 +504,11 @@ nxt_isolation_set_automount(nxt_task_t *task, nxt_conf_value_t *isolation, if (value != NULL) { automount->tmpfs = nxt_conf_get_boolean(value); } + + value = nxt_conf_get_object_member(conf, &proc_name, NULL); + if (value != NULL) { + automount->procfs = nxt_conf_get_boolean(value); + } } return NXT_OK; @@ -609,27 +616,29 @@ nxt_isolation_set_lang_mounts(nxt_task_t *task, nxt_process_t *process, *p = '\0'; } - mnt = nxt_array_add(mounts); - if (nxt_slow_path(mnt == NULL)) { - return NXT_ERROR; - } + if (process->isolation.automount.procfs) { + mnt = nxt_array_add(mounts); + if (nxt_slow_path(mnt == NULL)) { + return NXT_ERROR; + } - mnt->name = (u_char *) "proc"; - mnt->type = NXT_FS_PROC; - mnt->src = (u_char *) "none"; - mnt->dst = nxt_mp_nget(mp, rootfs_len + nxt_length("/proc") + 1); - if (nxt_slow_path(mnt->dst == NULL)) { - return NXT_ERROR; - } + mnt->name = (u_char *) "proc"; + mnt->type = NXT_FS_PROC; + mnt->src = (u_char *) "none"; + mnt->dst = nxt_mp_nget(mp, rootfs_len + nxt_length("/proc") + 1); + if (nxt_slow_path(mnt->dst == NULL)) { + return NXT_ERROR; + } - p = nxt_cpymem(mnt->dst, rootfs, rootfs_len); - p = nxt_cpymem(p, "/proc", 5); - *p = '\0'; + p = nxt_cpymem(mnt->dst, rootfs, rootfs_len); + p = nxt_cpymem(p, "/proc", 5); + *p = '\0'; - mnt->data = (u_char *) ""; - mnt->flags = NXT_FS_FLAGS_NOEXEC | NXT_FS_FLAGS_NOSUID; - mnt->builtin = 1; - mnt->deps = 0; + mnt->data = (u_char *) ""; + mnt->flags = NXT_FS_FLAGS_NOEXEC | NXT_FS_FLAGS_NOSUID; + mnt->builtin = 1; + mnt->deps = 0; + } qsort(mounts->elts, mounts->nelts, sizeof(nxt_fs_mount_t), nxt_isolation_mount_compare); -- cgit