Isolation: added "automount" option.

Now it's possible to disable default bind mounts of
languages by setting:

  {
      "isolation": {
           "automount": {
               "language_deps": false
           }
     }
  }

In this case, the user is responsible to provide a "rootfs"
containing the language libraries and required files for
the application.
This commit is contained in:
Tiago Natel de Moura
2020-08-25 15:25:51 +01:00
parent 244ffb2829
commit b65a8636bb
9 changed files with 112 additions and 34 deletions

View File

@@ -326,11 +326,11 @@ cat << END > $NXT_BUILD_DIR/$NXT_JAVA_MOUNTS_HEADER
static const nxt_fs_mount_t nxt_java_mounts[] = { static const nxt_fs_mount_t nxt_java_mounts[] = {
{(u_char *) "proc", (u_char *) "/proc", (u_char *) "proc", 0, NULL}, {(u_char *) "proc", (u_char *) "/proc", (u_char *) "proc", 0, NULL, 1},
{(u_char *) "$NXT_JAVA_LIBC_DIR", (u_char *) "$NXT_JAVA_LIBC_DIR", {(u_char *) "$NXT_JAVA_LIBC_DIR", (u_char *) "$NXT_JAVA_LIBC_DIR",
(u_char *) "bind", NXT_MS_BIND | NXT_MS_REC, NULL}, (u_char *) "bind", NXT_MS_BIND | NXT_MS_REC, NULL, 1},
{(u_char *) "$NXT_JAVA_HOME", (u_char *) "$NXT_JAVA_HOME", {(u_char *) "$NXT_JAVA_HOME", (u_char *) "$NXT_JAVA_HOME",
(u_char *) "bind", NXT_MS_BIND | NXT_MS_REC, NULL}, (u_char *) "bind", NXT_MS_BIND | NXT_MS_REC, NULL, 1},
}; };

View File

@@ -233,11 +233,11 @@ NXT_PHP_MOUNTS_HEADER=nxt_${NXT_PHP_MODULE}_mounts.h
cat << END > $NXT_BUILD_DIR/$NXT_PHP_MOUNTS_HEADER cat << END > $NXT_BUILD_DIR/$NXT_PHP_MOUNTS_HEADER
static const nxt_fs_mount_t nxt_php_mounts[] = { static const nxt_fs_mount_t nxt_php_mounts[] = {
{(u_char *) "$NXT_PHP_EXT_DIR", (u_char *) "$NXT_PHP_EXT_DIR", {(u_char *) "$NXT_PHP_EXT_DIR", (u_char *) "$NXT_PHP_EXT_DIR",
(u_char *) "bind", NXT_MS_BIND | NXT_MS_REC, NULL}, (u_char *) "bind", NXT_MS_BIND | NXT_MS_REC, NULL, 1},
{(u_char *) "$NXT_PHP_LIBC_DIR", (u_char *) "$NXT_PHP_LIBC_DIR", {(u_char *) "$NXT_PHP_LIBC_DIR", (u_char *) "$NXT_PHP_LIBC_DIR",
(u_char *) "bind", NXT_MS_BIND | NXT_MS_REC, NULL}, (u_char *) "bind", NXT_MS_BIND | NXT_MS_REC, NULL, 1},
{(u_char *) "$NXT_PHP_SYSLIB_DIR", (u_char *) "$NXT_PHP_SYSLIB_DIR", {(u_char *) "$NXT_PHP_SYSLIB_DIR", (u_char *) "$NXT_PHP_SYSLIB_DIR",
(u_char *) "bind", NXT_MS_BIND | NXT_MS_REC, NULL}, (u_char *) "bind", NXT_MS_BIND | NXT_MS_REC, NULL, 1},
}; };
END END

View File

@@ -138,7 +138,7 @@ pyver = "python" + str(sys.version_info[0]) + "." + str(sys.version_info[1])
print("static const nxt_fs_mount_t nxt_python_mounts[] = {") print("static const nxt_fs_mount_t nxt_python_mounts[] = {")
pattern = "{(u_char *) \"%s\", (u_char *) \"%s\", (u_char *) \"bind\", NXT_MS_BIND|NXT_MS_REC, NULL}," pattern = "{(u_char *) \"%s\", (u_char *) \"%s\", (u_char *) \"bind\", NXT_MS_BIND|NXT_MS_REC, NULL, 1},"
base = None base = None
for p in sys.path: for p in sys.path:
if len(p) > 0: if len(p) > 0:

View File

@@ -156,23 +156,23 @@ cat << END > $NXT_RUBY_MOUNTS_PATH
static const nxt_fs_mount_t nxt_ruby_mounts[] = { static const nxt_fs_mount_t nxt_ruby_mounts[] = {
{(u_char *) "$NXT_RUBY_RUBYHDRDIR", (u_char *) "$NXT_RUBY_RUBYHDRDIR", {(u_char *) "$NXT_RUBY_RUBYHDRDIR", (u_char *) "$NXT_RUBY_RUBYHDRDIR",
(u_char *) "bind", NXT_MS_BIND | NXT_MS_REC, NULL}, (u_char *) "bind", NXT_MS_BIND | NXT_MS_REC, NULL, 1},
{(u_char *) "$NXT_RUBY_ARCHHDRDIR", (u_char *) "$NXT_RUBY_ARCHHDRDIR", {(u_char *) "$NXT_RUBY_ARCHHDRDIR", (u_char *) "$NXT_RUBY_ARCHHDRDIR",
(u_char *) "bind", NXT_MS_BIND | NXT_MS_REC, NULL}, (u_char *) "bind", NXT_MS_BIND | NXT_MS_REC, NULL, 1},
{(u_char *) "$NXT_RUBY_SITEDIR", (u_char *) "$NXT_RUBY_SITEDIR", {(u_char *) "$NXT_RUBY_SITEDIR", (u_char *) "$NXT_RUBY_SITEDIR",
(u_char *) "bind", NXT_MS_BIND | NXT_MS_REC, NULL}, (u_char *) "bind", NXT_MS_BIND | NXT_MS_REC, NULL, 1},
{(u_char *) "$NXT_RUBY_LIBDIR", (u_char *) "$NXT_RUBY_LIBDIR", {(u_char *) "$NXT_RUBY_LIBDIR", (u_char *) "$NXT_RUBY_LIBDIR",
(u_char *) "bind", NXT_MS_BIND | NXT_MS_REC, NULL}, (u_char *) "bind", NXT_MS_BIND | NXT_MS_REC, NULL, 1},
{(u_char *) "$NXT_RUBY_TOPDIR", (u_char *) "$NXT_RUBY_TOPDIR", {(u_char *) "$NXT_RUBY_TOPDIR", (u_char *) "$NXT_RUBY_TOPDIR",
(u_char *) "bind", NXT_MS_BIND | NXT_MS_REC, NULL}, (u_char *) "bind", NXT_MS_BIND | NXT_MS_REC, NULL, 1},
{(u_char *) "$NXT_RUBY_PREFIXDIR", (u_char *) "$NXT_RUBY_PREFIXDIR", {(u_char *) "$NXT_RUBY_PREFIXDIR", (u_char *) "$NXT_RUBY_PREFIXDIR",
(u_char *) "bind", NXT_MS_BIND | NXT_MS_REC, NULL}, (u_char *) "bind", NXT_MS_BIND | NXT_MS_REC, NULL, 1},
END END
for path in `echo $NXT_RUBY_GEMPATH | tr ':' '\n'`; do for path in `echo $NXT_RUBY_GEMPATH | tr ':' '\n'`; do
$echo "{(u_char *) \"$path\", (u_char *) \"$path\"," >> $NXT_RUBY_MOUNTS_PATH $echo "{(u_char *) \"$path\", (u_char *) \"$path\"," >> $NXT_RUBY_MOUNTS_PATH
$echo "(u_char *) \"bind\", NXT_MS_BIND | NXT_MS_REC, NULL}," >> $NXT_RUBY_MOUNTS_PATH $echo "(u_char *) \"bind\", NXT_MS_BIND | NXT_MS_REC, NULL, 1}," >> $NXT_RUBY_MOUNTS_PATH
done done
$echo "};" >> $NXT_RUBY_MOUNTS_PATH $echo "};" >> $NXT_RUBY_MOUNTS_PATH

View File

@@ -616,6 +616,21 @@ static nxt_conf_vldt_object_t nxt_conf_vldt_app_procmap_members[] = {
#endif #endif
#if (NXT_HAVE_ISOLATION_ROOTFS)
static nxt_conf_vldt_object_t nxt_conf_vldt_app_automount_members[] = {
{ nxt_string("language_deps"),
NXT_CONF_VLDT_BOOLEAN,
0,
NULL,
NULL },
NXT_CONF_VLDT_END
};
#endif
static nxt_conf_vldt_object_t nxt_conf_vldt_app_isolation_members[] = { static nxt_conf_vldt_object_t nxt_conf_vldt_app_isolation_members[] = {
{ nxt_string("namespaces"), { nxt_string("namespaces"),
NXT_CONF_VLDT_OBJECT, NXT_CONF_VLDT_OBJECT,
@@ -647,6 +662,12 @@ static nxt_conf_vldt_object_t nxt_conf_vldt_app_isolation_members[] = {
NULL, NULL,
NULL }, NULL },
{ nxt_string("automount"),
NXT_CONF_VLDT_OBJECT,
0,
&nxt_conf_vldt_object,
(void *) &nxt_conf_vldt_app_automount_members },
#endif #endif
#if (NXT_HAVE_PR_SET_NO_NEW_PRIVS) #if (NXT_HAVE_PR_SET_NO_NEW_PRIVS)

View File

@@ -44,11 +44,12 @@
typedef struct { typedef struct {
u_char *src; u_char *src;
u_char *dst; u_char *dst;
u_char *fstype; u_char *fstype;
nxt_int_t flags; nxt_int_t flags;
u_char *data; u_char *data;
nxt_uint_t builtin; /* 1-bit */
} nxt_fs_mount_t; } nxt_fs_mount_t;

View File

@@ -35,6 +35,8 @@ static nxt_int_t nxt_isolation_vldt_creds(nxt_task_t *task,
#if (NXT_HAVE_ISOLATION_ROOTFS) #if (NXT_HAVE_ISOLATION_ROOTFS)
static nxt_int_t nxt_isolation_set_rootfs(nxt_task_t *task, static nxt_int_t nxt_isolation_set_rootfs(nxt_task_t *task,
nxt_conf_value_t *isolation, nxt_process_t *process); nxt_conf_value_t *isolation, nxt_process_t *process);
static nxt_int_t nxt_isolation_set_automount(nxt_task_t *task,
nxt_conf_value_t *isolation, nxt_process_t *process);
static nxt_int_t nxt_isolation_set_mounts(nxt_task_t *task, static nxt_int_t nxt_isolation_set_mounts(nxt_task_t *task,
nxt_process_t *process, nxt_str_t *app_type); nxt_process_t *process, nxt_str_t *app_type);
static nxt_int_t nxt_isolation_set_lang_mounts(nxt_task_t *task, static nxt_int_t nxt_isolation_set_lang_mounts(nxt_task_t *task,
@@ -159,6 +161,12 @@ nxt_isolation_set(nxt_task_t *task, nxt_conf_value_t *isolation,
{ {
return NXT_ERROR; return NXT_ERROR;
} }
if (nxt_slow_path(nxt_isolation_set_automount(task, isolation, process)
!= NXT_OK))
{
return NXT_ERROR;
}
#endif #endif
#if (NXT_HAVE_PR_SET_NO_NEW_PRIVS) #if (NXT_HAVE_PR_SET_NO_NEW_PRIVS)
@@ -451,6 +459,32 @@ nxt_isolation_set_rootfs(nxt_task_t *task, nxt_conf_value_t *isolation,
} }
static nxt_int_t
nxt_isolation_set_automount(nxt_task_t *task, nxt_conf_value_t *isolation,
nxt_process_t *process)
{
nxt_conf_value_t *conf, *value;
nxt_process_automount_t *automount;
static nxt_str_t automount_name = nxt_string("automount");
static nxt_str_t langdeps_name = nxt_string("language_deps");
automount = &process->isolation.automount;
automount->language_deps = 1;
conf = nxt_conf_get_object_member(isolation, &automount_name, NULL);
if (conf != NULL) {
value = nxt_conf_get_object_member(conf, &langdeps_name, NULL);
if (value != NULL) {
automount->language_deps = nxt_conf_get_boolean(value);
}
}
return NXT_OK;
}
static nxt_int_t static nxt_int_t
nxt_isolation_set_mounts(nxt_task_t *task, nxt_process_t *process, nxt_isolation_set_mounts(nxt_task_t *task, nxt_process_t *process,
nxt_str_t *app_type) nxt_str_t *app_type)
@@ -535,6 +569,7 @@ nxt_isolation_set_lang_mounts(nxt_task_t *task, nxt_process_t *process,
mnt->fstype = (u_char *) "tmpfs"; mnt->fstype = (u_char *) "tmpfs";
mnt->flags = NXT_MS_NOSUID | NXT_MS_NODEV | NXT_MS_NOEXEC | NXT_MS_RELATIME; mnt->flags = NXT_MS_NOSUID | NXT_MS_NODEV | NXT_MS_NOEXEC | NXT_MS_RELATIME;
mnt->data = (u_char *) "size=1m,mode=777"; mnt->data = (u_char *) "size=1m,mode=777";
mnt->builtin = 1;
mnt->dst = nxt_mp_nget(mp, rootfs_len + nxt_length("/tmp") + 1); mnt->dst = nxt_mp_nget(mp, rootfs_len + nxt_length("/tmp") + 1);
if (nxt_slow_path(mnt->dst == NULL)) { if (nxt_slow_path(mnt->dst == NULL)) {
@@ -581,17 +616,23 @@ nxt_isolation_set_lang_mounts(nxt_task_t *task, nxt_process_t *process,
void void
nxt_isolation_unmount_all(nxt_task_t *task, nxt_process_t *process) nxt_isolation_unmount_all(nxt_task_t *task, nxt_process_t *process)
{ {
size_t i, n; size_t i, n;
nxt_array_t *mounts; nxt_array_t *mounts;
nxt_fs_mount_t *mnt; nxt_fs_mount_t *mnt;
nxt_process_automount_t *automount;
nxt_debug(task, "unmount all (%s)", process->name); nxt_debug(task, "unmount all (%s)", process->name);
automount = &process->isolation.automount;
mounts = process->isolation.mounts; mounts = process->isolation.mounts;
n = mounts->nelts; n = mounts->nelts;
mnt = mounts->elts; mnt = mounts->elts;
for (i = 0; i < n; i++) { for (i = 0; i < n; i++) {
if (mnt[i].builtin && !automount->language_deps) {
continue;
}
nxt_fs_unmount(mnt[i].dst); nxt_fs_unmount(mnt[i].dst);
} }
} }
@@ -600,13 +641,15 @@ nxt_isolation_unmount_all(nxt_task_t *task, nxt_process_t *process)
nxt_int_t nxt_int_t
nxt_isolation_prepare_rootfs(nxt_task_t *task, nxt_process_t *process) nxt_isolation_prepare_rootfs(nxt_task_t *task, nxt_process_t *process)
{ {
size_t i, n; size_t i, n;
nxt_int_t ret; nxt_int_t ret;
struct stat st; struct stat st;
nxt_array_t *mounts; nxt_array_t *mounts;
const u_char *dst; const u_char *dst;
nxt_fs_mount_t *mnt; nxt_fs_mount_t *mnt;
nxt_process_automount_t *automount;
automount = &process->isolation.automount;
mounts = process->isolation.mounts; mounts = process->isolation.mounts;
n = mounts->nelts; n = mounts->nelts;
@@ -615,6 +658,10 @@ nxt_isolation_prepare_rootfs(nxt_task_t *task, nxt_process_t *process)
for (i = 0; i < n; i++) { for (i = 0; i < n; i++) {
dst = mnt[i].dst; dst = mnt[i].dst;
if (mnt[i].builtin && !automount->language_deps) {
continue;
}
if (nxt_slow_path(nxt_memcmp(mnt[i].fstype, "bind", 4) == 0 if (nxt_slow_path(nxt_memcmp(mnt[i].fstype, "bind", 4) == 0
&& stat((const char *) mnt[i].src, &st) != 0)) && stat((const char *) mnt[i].src, &st) != 0))
{ {

View File

@@ -1290,6 +1290,8 @@ nxt_main_port_modules_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg)
goto fail; goto fail;
} }
mnt->builtin = 1;
ret = nxt_conf_map_object(rt->mem_pool, value, ret = nxt_conf_map_object(rt->mem_pool, value,
nxt_app_lang_mounts_map, nxt_app_lang_mounts_map,
nxt_nitems(nxt_app_lang_mounts_map), mnt); nxt_nitems(nxt_app_lang_mounts_map), mnt);

View File

@@ -72,18 +72,25 @@ typedef struct {
nxt_port_mmap_t *elts; nxt_port_mmap_t *elts;
} nxt_port_mmaps_t; } nxt_port_mmaps_t;
typedef struct {
u_char *rootfs;
nxt_array_t *mounts; /* of nxt_mount_t */
nxt_isolation_cleanup_t cleanup; typedef struct {
uint8_t language_deps; /* 1-byte */
} nxt_process_automount_t;
typedef struct {
u_char *rootfs;
nxt_process_automount_t automount;
nxt_array_t *mounts; /* of nxt_mount_t */
nxt_isolation_cleanup_t cleanup;
#if (NXT_HAVE_CLONE) #if (NXT_HAVE_CLONE)
nxt_clone_t clone; nxt_clone_t clone;
#endif #endif
#if (NXT_HAVE_PR_SET_NO_NEW_PRIVS) #if (NXT_HAVE_PR_SET_NO_NEW_PRIVS)
uint8_t new_privs; /* 1 bit */ uint8_t new_privs; /* 1 bit */
#endif #endif
} nxt_process_isolation_t; } nxt_process_isolation_t;