Added "rootfs" feature.
This commit is contained in:
130
auto/isolation
130
auto/isolation
@@ -6,6 +6,9 @@
|
|||||||
NXT_ISOLATION=NO
|
NXT_ISOLATION=NO
|
||||||
NXT_HAVE_CLONE=NO
|
NXT_HAVE_CLONE=NO
|
||||||
NXT_HAVE_CLONE_NEWUSER=NO
|
NXT_HAVE_CLONE_NEWUSER=NO
|
||||||
|
NXT_HAVE_MOUNT=NO
|
||||||
|
NXT_HAVE_UNMOUNT=NO
|
||||||
|
NXT_HAVE_ROOTFS=NO
|
||||||
|
|
||||||
nsflags="USER NS PID NET UTS CGROUP"
|
nsflags="USER NS PID NET UTS CGROUP"
|
||||||
|
|
||||||
@@ -55,3 +58,130 @@ if [ $nxt_found = yes ]; then
|
|||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
nxt_feature="Linux pivot_root()"
|
||||||
|
nxt_feature_name=NXT_HAVE_PIVOT_ROOT
|
||||||
|
nxt_feature_run=no
|
||||||
|
nxt_feature_incs=
|
||||||
|
nxt_feature_libs=
|
||||||
|
nxt_feature_test="#include <sys/syscall.h>
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
return __NR_pivot_root;
|
||||||
|
}"
|
||||||
|
. auto/feature
|
||||||
|
|
||||||
|
|
||||||
|
nxt_feature="prctl(PR_SET_NO_NEW_PRIVS)"
|
||||||
|
nxt_feature_name=NXT_HAVE_PR_SET_NO_NEW_PRIVS0
|
||||||
|
nxt_feature_run=no
|
||||||
|
nxt_feature_incs=
|
||||||
|
nxt_feature_libs=
|
||||||
|
nxt_feature_test="#include <sys/prctl.h>
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
return PR_SET_NO_NEW_PRIVS;
|
||||||
|
}"
|
||||||
|
. auto/feature
|
||||||
|
|
||||||
|
|
||||||
|
nxt_feature="Linux mount()"
|
||||||
|
nxt_feature_name=NXT_HAVE_LINUX_MOUNT
|
||||||
|
nxt_feature_run=no
|
||||||
|
nxt_feature_incs=
|
||||||
|
nxt_feature_libs=
|
||||||
|
nxt_feature_test="#include <sys/mount.h>
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
return mount((void*)0, (void*)0, (void*)0, 0, (void*)0);
|
||||||
|
}"
|
||||||
|
. auto/feature
|
||||||
|
|
||||||
|
if [ $nxt_found = yes ]; then
|
||||||
|
NXT_HAVE_MOUNT=YES
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
nxt_feature="Bind mount()"
|
||||||
|
nxt_feature_name=NXT_HAVE_BIND_MOUNT
|
||||||
|
nxt_feature_run=no
|
||||||
|
nxt_feature_incs=
|
||||||
|
nxt_feature_libs=
|
||||||
|
nxt_feature_test="#include <sys/mount.h>
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
return MS_BIND | MS_REC
|
||||||
|
}"
|
||||||
|
. auto/feature
|
||||||
|
|
||||||
|
if [ $nxt_found = yes ]; then
|
||||||
|
NXT_HAVE_MOUNT=YES
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
if [ $nxt_found = no ]; then
|
||||||
|
nxt_feature="FreeBSD nmount()"
|
||||||
|
nxt_feature_name=NXT_HAVE_FREEBSD_NMOUNT
|
||||||
|
nxt_feature_run=no
|
||||||
|
nxt_feature_incs=
|
||||||
|
nxt_feature_libs=
|
||||||
|
nxt_feature_test="#include <sys/mount.h>
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
return nmount((void *)0, 0, 0);
|
||||||
|
}"
|
||||||
|
. auto/feature
|
||||||
|
|
||||||
|
if [ $nxt_found = yes ]; then
|
||||||
|
NXT_HAVE_MOUNT=YES
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
nxt_feature="Linux umount2()"
|
||||||
|
nxt_feature_name=NXT_HAVE_LINUX_UMOUNT2
|
||||||
|
nxt_feature_run=no
|
||||||
|
nxt_feature_incs=
|
||||||
|
nxt_feature_libs=
|
||||||
|
nxt_feature_test="#include <sys/mount.h>
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
return umount2((void *)0, 0);
|
||||||
|
}"
|
||||||
|
. auto/feature
|
||||||
|
|
||||||
|
if [ $nxt_found = yes ]; then
|
||||||
|
NXT_HAVE_UNMOUNT=YES
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ $nxt_found = no ]; then
|
||||||
|
nxt_feature="unmount()"
|
||||||
|
nxt_feature_name=NXT_HAVE_UNMOUNT
|
||||||
|
nxt_feature_run=no
|
||||||
|
nxt_feature_incs=
|
||||||
|
nxt_feature_libs=
|
||||||
|
nxt_feature_test="#include <sys/mount.h>
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
return unmount((void *)0, 0);
|
||||||
|
}"
|
||||||
|
. auto/feature
|
||||||
|
|
||||||
|
if [ $nxt_found = yes ]; then
|
||||||
|
NXT_HAVE_UNMOUNT=YES
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ $NXT_HAVE_MOUNT = YES -a $NXT_HAVE_UNMOUNT = YES ]; then
|
||||||
|
NXT_HAVE_ROOTFS=YES
|
||||||
|
|
||||||
|
cat << END >> $NXT_AUTO_CONFIG_H
|
||||||
|
|
||||||
|
#ifndef NXT_HAVE_ISOLATION_ROOTFS
|
||||||
|
#define NXT_HAVE_ISOLATION_ROOTFS 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
END
|
||||||
|
|
||||||
|
fi
|
||||||
|
|||||||
@@ -172,13 +172,13 @@ if [ -z "$NXT_JAVA_LIB_PATH" ]; then
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
NXT_JAVA_LIB_PATH="${NXT_JAVA_LIB_PATH}/server"
|
NXT_JAVA_LIB_SERVER_PATH="${NXT_JAVA_LIB_PATH}/server"
|
||||||
|
|
||||||
$echo " $NXT_JAVA_LIB_PATH"
|
$echo " $NXT_JAVA_LIB_PATH"
|
||||||
$echo "got library path $NXT_JAVA_LIB_PATH" >> $NXT_AUTOCONF_ERR
|
$echo "got library path $NXT_JAVA_LIB_PATH" >> $NXT_AUTOCONF_ERR
|
||||||
fi
|
fi
|
||||||
|
|
||||||
NXT_JAVA_LDFLAGS="-L${NXT_JAVA_LIB_PATH} -Wl,-rpath ${NXT_JAVA_LIB_PATH} -ljvm"
|
NXT_JAVA_LDFLAGS="-L${NXT_JAVA_LIB_SERVER_PATH} -Wl,-rpath ${NXT_JAVA_LIB_SERVER_PATH} -ljvm"
|
||||||
|
|
||||||
|
|
||||||
nxt_found=no
|
nxt_found=no
|
||||||
@@ -227,6 +227,7 @@ NXT_JAVA_INSTALL_JARS=
|
|||||||
NXT_JAVA_UNINSTALL_JARS=
|
NXT_JAVA_UNINSTALL_JARS=
|
||||||
|
|
||||||
NXT_JAVA_JARS=$NXT_BUILD_DIR/$NXT_JAVA_MODULE/nxt_jars.h
|
NXT_JAVA_JARS=$NXT_BUILD_DIR/$NXT_JAVA_MODULE/nxt_jars.h
|
||||||
|
NXT_JAVA_MOUNTS_HEADER=$NXT_BUILD_DIR/$NXT_JAVA_MODULE/nxt_java_mounts.h
|
||||||
mkdir -p $NXT_BUILD_DIR/$NXT_JAVA_MODULE
|
mkdir -p $NXT_BUILD_DIR/$NXT_JAVA_MODULE
|
||||||
|
|
||||||
cat << END > $NXT_JAVA_JARS
|
cat << END > $NXT_JAVA_JARS
|
||||||
@@ -308,6 +309,32 @@ cat << END >> $NXT_JAVA_JARS
|
|||||||
#endif /* _NXT_JAVA_JARS_INCLUDED_ */
|
#endif /* _NXT_JAVA_JARS_INCLUDED_ */
|
||||||
END
|
END
|
||||||
|
|
||||||
|
NXT_JAVA_LIBJVM="$NXT_JAVA_LIB_SERVER_PATH/libjvm.so"
|
||||||
|
|
||||||
|
if [ "$NXT_SYSTEM" = "Darwin" ]; then
|
||||||
|
NXT_JAVA_LIBC_DIR="/usr/lib"
|
||||||
|
else
|
||||||
|
NXT_JAVA_LIBC_DIR=`ldd "$NXT_JAVA_LIBJVM" | grep libc.so | cut -d' ' -f3`
|
||||||
|
NXT_JAVA_LIBC_DIR=`dirname $NXT_JAVA_LIBC_DIR`
|
||||||
|
fi
|
||||||
|
|
||||||
|
cat << END > $NXT_JAVA_MOUNTS_HEADER
|
||||||
|
#ifndef _NXT_JAVA_MOUNTS_H_INCLUDED_
|
||||||
|
#define _NXT_JAVA_MOUNTS_H_INCLUDED_
|
||||||
|
|
||||||
|
|
||||||
|
static const nxt_fs_mount_t nxt_java_mounts[] = {
|
||||||
|
{(u_char *) "proc", (u_char *) "/proc", (u_char *) "proc", 0, NULL},
|
||||||
|
{(u_char *) "$NXT_JAVA_LIBC_DIR", (u_char *) "$NXT_JAVA_LIBC_DIR",
|
||||||
|
(u_char *) "bind", NXT_MS_BIND | NXT_MS_REC, NULL},
|
||||||
|
{(u_char *) "$NXT_JAVA_HOME", (u_char *) "$NXT_JAVA_HOME",
|
||||||
|
(u_char *) "bind", NXT_MS_BIND | NXT_MS_REC, NULL},
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* _NXT_JAVA_MOUNTS_H_INCLUDED_ */
|
||||||
|
END
|
||||||
|
|
||||||
$echo " + Java module: ${NXT_JAVA_MODULE}.unit.so"
|
$echo " + Java module: ${NXT_JAVA_MODULE}.unit.so"
|
||||||
|
|
||||||
. auto/cc/deps
|
. auto/cc/deps
|
||||||
|
|||||||
@@ -68,6 +68,7 @@ if /bin/sh -c "$NXT_PYTHON_CONFIG --prefix" >> $NXT_AUTOCONF_ERR 2>&1; then
|
|||||||
NXT_PYTHON_CONFIG="${NXT_PYTHON_CONFIG} --embed"
|
NXT_PYTHON_CONFIG="${NXT_PYTHON_CONFIG} --embed"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
NXT_PYTHON_EXEC=`${NXT_PYTHON_CONFIG} --exec-prefix`/bin/${NXT_PYTHON}
|
||||||
NXT_PYTHON_INCLUDE=`${NXT_PYTHON_CONFIG} --includes`
|
NXT_PYTHON_INCLUDE=`${NXT_PYTHON_CONFIG} --includes`
|
||||||
NXT_PYTHON_LIBS=`${NXT_PYTHON_CONFIG} --ldflags`
|
NXT_PYTHON_LIBS=`${NXT_PYTHON_CONFIG} --ldflags`
|
||||||
|
|
||||||
@@ -129,6 +130,37 @@ if grep ^$NXT_PYTHON_MODULE: $NXT_MAKEFILE 2>&1 > /dev/null; then
|
|||||||
exit 1;
|
exit 1;
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
NXT_PYTHON_MOUNTS_HEADER=$NXT_BUILD_DIR/nxt_python_mounts.h
|
||||||
|
|
||||||
|
$NXT_PYTHON_EXEC -c 'import os.path
|
||||||
|
import sys
|
||||||
|
pyver = "python" + str(sys.version_info[0]) + "." + str(sys.version_info[1])
|
||||||
|
|
||||||
|
print("static const nxt_fs_mount_t nxt_python%d%d_mounts[] = {" % (sys.version_info[0], sys.version_info[1]))
|
||||||
|
|
||||||
|
pattern = "{(u_char *) \"%s\", (u_char *) \"%s\", (u_char *) \"bind\", NXT_MS_BIND|NXT_MS_REC, NULL},"
|
||||||
|
base = None
|
||||||
|
for p in sys.path:
|
||||||
|
if len(p) > 0:
|
||||||
|
if os.path.basename(p) == pyver:
|
||||||
|
base = p
|
||||||
|
|
||||||
|
if base is None:
|
||||||
|
raise Exception("failed to compute sys.path mount points")
|
||||||
|
|
||||||
|
print(pattern % (base, base))
|
||||||
|
|
||||||
|
for p in sys.path:
|
||||||
|
if len(p) > 0:
|
||||||
|
if not p.startswith(base):
|
||||||
|
print(pattern % (p, p))
|
||||||
|
|
||||||
|
print("};\n\n")
|
||||||
|
|
||||||
|
' >> $NXT_PYTHON_MOUNTS_HEADER
|
||||||
|
|
||||||
|
|
||||||
$echo " + Python module: ${NXT_PYTHON_MODULE}.unit.so"
|
$echo " + Python module: ${NXT_PYTHON_MODULE}.unit.so"
|
||||||
|
|
||||||
. auto/cc/deps
|
. auto/cc/deps
|
||||||
|
|||||||
@@ -51,6 +51,7 @@ $echo "configuring Ruby module ..." >> $NXT_AUTOCONF_ERR
|
|||||||
|
|
||||||
NXT_RUBY=${NXT_RUBY=ruby}
|
NXT_RUBY=${NXT_RUBY=ruby}
|
||||||
NXT_RUBY_MODULE=${NXT_RUBY_MODULE=${NXT_RUBY}}
|
NXT_RUBY_MODULE=${NXT_RUBY_MODULE=${NXT_RUBY}}
|
||||||
|
NXT_RUBY_MOUNTS_HEADER=$NXT_BUILD_DIR/nxt_ruby_mounts.h
|
||||||
|
|
||||||
nxt_found=no
|
nxt_found=no
|
||||||
|
|
||||||
@@ -58,6 +59,14 @@ if /bin/sh -c "$NXT_RUBY -v" >> $NXT_AUTOCONF_ERR 2>&1; then
|
|||||||
|
|
||||||
NXT_RUBY_RUBYHDRDIR=`$NXT_RUBY -r rbconfig -e 'printf("%s",RbConfig::CONFIG["rubyhdrdir"])'`
|
NXT_RUBY_RUBYHDRDIR=`$NXT_RUBY -r rbconfig -e 'printf("%s",RbConfig::CONFIG["rubyhdrdir"])'`
|
||||||
NXT_RUBY_ARCHHDRDIR=`$NXT_RUBY -r rbconfig -e 'printf("%s",RbConfig::CONFIG["rubyarchhdrdir"])'`
|
NXT_RUBY_ARCHHDRDIR=`$NXT_RUBY -r rbconfig -e 'printf("%s",RbConfig::CONFIG["rubyarchhdrdir"])'`
|
||||||
|
NXT_RUBY_SITEARCHDIR=`$NXT_RUBY -r rbconfig -e 'printf("%s",RbConfig::CONFIG["sitearchhdrdir"])'`
|
||||||
|
NXT_RUBY_SITEDIR=`$NXT_RUBY -r rbconfig -e 'printf("%s",RbConfig::CONFIG["sitedir"])'`
|
||||||
|
NXT_RUBY_LIBDIR=`$NXT_RUBY -r rbconfig -e 'printf("%s",RbConfig::CONFIG["rubylibdir"])'`
|
||||||
|
NXT_RUBY_TOPDIR=`$NXT_RUBY -r rbconfig -e 'printf("%s",RbConfig::CONFIG["topdir"])'`
|
||||||
|
NXT_RUBY_PREFIXDIR=`$NXT_RUBY -r rbconfig -e 'printf("%s",RbConfig::CONFIG["rubylibprefix"])'`
|
||||||
|
NXT_RUBY_GEMDIR=`gem environment gemdir`
|
||||||
|
NXT_RUBY_GEMPATH=`gem environment gempath`
|
||||||
|
|
||||||
NXT_RUBY_INCPATH="-I$NXT_RUBY_ARCHHDRDIR -I$NXT_RUBY_RUBYHDRDIR"
|
NXT_RUBY_INCPATH="-I$NXT_RUBY_ARCHHDRDIR -I$NXT_RUBY_RUBYHDRDIR"
|
||||||
|
|
||||||
NXT_RUBY_LIBNAME=`$NXT_RUBY -r rbconfig -e 'printf("%s",RbConfig::CONFIG["RUBY_SO_NAME"])'`
|
NXT_RUBY_LIBNAME=`$NXT_RUBY -r rbconfig -e 'printf("%s",RbConfig::CONFIG["RUBY_SO_NAME"])'`
|
||||||
@@ -135,6 +144,35 @@ if grep ^$NXT_RUBY_MODULE: $NXT_MAKEFILE 2>&1 > /dev/null; then
|
|||||||
exit 1;
|
exit 1;
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
cat << END > $NXT_RUBY_MOUNTS_HEADER
|
||||||
|
|
||||||
|
static const nxt_fs_mount_t nxt_ruby_mounts[] = {
|
||||||
|
{(u_char *) "$NXT_RUBY_RUBYHDRDIR", (u_char *) "$NXT_RUBY_RUBYHDRDIR",
|
||||||
|
(u_char *) "bind", NXT_MS_BIND | NXT_MS_REC, NULL},
|
||||||
|
{(u_char *) "$NXT_RUBY_ARCHHDRDIR", (u_char *) "$NXT_RUBY_ARCHHDRDIR",
|
||||||
|
(u_char *) "bind", NXT_MS_BIND | NXT_MS_REC, NULL},
|
||||||
|
{(u_char *) "$NXT_RUBY_SITEDIR", (u_char *) "$NXT_RUBY_SITEDIR",
|
||||||
|
(u_char *) "bind", NXT_MS_BIND | NXT_MS_REC, NULL},
|
||||||
|
{(u_char *) "$NXT_RUBY_LIBDIR", (u_char *) "$NXT_RUBY_LIBDIR",
|
||||||
|
(u_char *) "bind", NXT_MS_BIND | NXT_MS_REC, NULL},
|
||||||
|
{(u_char *) "$NXT_RUBY_GEMDIR", (u_char *) "$NXT_RUBY_GEMDIR",
|
||||||
|
(u_char *) "bind", NXT_MS_BIND | NXT_MS_REC, NULL},
|
||||||
|
{(u_char *) "$NXT_RUBY_TOPDIR", (u_char *) "$NXT_RUBY_TOPDIR",
|
||||||
|
(u_char *) "bind", NXT_MS_BIND | NXT_MS_REC, NULL},
|
||||||
|
{(u_char *) "$NXT_RUBY_PREFIXDIR", (u_char *) "$NXT_RUBY_PREFIXDIR",
|
||||||
|
(u_char *) "bind", NXT_MS_BIND | NXT_MS_REC, NULL},
|
||||||
|
|
||||||
|
END
|
||||||
|
|
||||||
|
for path in `echo $NXT_RUBY_GEMPATH | tr ':' '\n'`; do
|
||||||
|
$echo "{(u_char *) \"$path\", (u_char *) \"$path\"," >> $NXT_RUBY_MOUNTS_HEADER
|
||||||
|
$echo "(u_char *) \"bind\", NXT_MS_BIND | NXT_MS_REC, NULL}," >> $NXT_RUBY_MOUNTS_HEADER
|
||||||
|
done
|
||||||
|
|
||||||
|
$echo "};" >> $NXT_RUBY_MOUNTS_HEADER
|
||||||
|
|
||||||
|
|
||||||
$echo " + Ruby module: ${NXT_RUBY_MODULE}.unit.so"
|
$echo " + Ruby module: ${NXT_RUBY_MODULE}.unit.so"
|
||||||
|
|
||||||
. auto/cc/deps
|
. auto/cc/deps
|
||||||
|
|||||||
@@ -177,6 +177,11 @@ NXT_LIB_UTF8_FILE_NAME_TEST_SRCS=" \
|
|||||||
"
|
"
|
||||||
|
|
||||||
|
|
||||||
|
if [ $NXT_HAVE_ROOTFS = YES ]; then
|
||||||
|
NXT_LIB_SRCS="$NXT_LIB_SRCS src/nxt_fs.c"
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
if [ $NXT_TLS = YES ]; then
|
if [ $NXT_TLS = YES ]; then
|
||||||
nxt_have=NXT_TLS . auto/have
|
nxt_have=NXT_TLS . auto/have
|
||||||
NXT_LIB_SRCS="$NXT_LIB_SRCS $NXT_LIB_TLS_SRCS"
|
NXT_LIB_SRCS="$NXT_LIB_SRCS $NXT_LIB_TLS_SRCS"
|
||||||
|
|||||||
@@ -17,11 +17,16 @@
|
|||||||
|
|
||||||
#include <glob.h>
|
#include <glob.h>
|
||||||
|
|
||||||
|
#if (NXT_HAVE_PR_SET_NO_NEW_PRIVS)
|
||||||
|
#include <sys/prctl.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
nxt_app_type_t type;
|
nxt_app_type_t type;
|
||||||
nxt_str_t version;
|
nxt_str_t version;
|
||||||
nxt_str_t file;
|
nxt_str_t file;
|
||||||
|
nxt_array_t *mounts;
|
||||||
} nxt_module_t;
|
} nxt_module_t;
|
||||||
|
|
||||||
|
|
||||||
@@ -40,22 +45,40 @@ static nxt_int_t nxt_app_prefork(nxt_task_t *task, nxt_process_t *process,
|
|||||||
nxt_mp_t *mp);
|
nxt_mp_t *mp);
|
||||||
static nxt_int_t nxt_app_setup(nxt_task_t *task, nxt_process_t *process);
|
static nxt_int_t nxt_app_setup(nxt_task_t *task, nxt_process_t *process);
|
||||||
static nxt_int_t nxt_app_set_environment(nxt_conf_value_t *environment);
|
static nxt_int_t nxt_app_set_environment(nxt_conf_value_t *environment);
|
||||||
static nxt_int_t nxt_app_isolation(nxt_task_t *task,
|
static u_char *nxt_cstr_dup(nxt_mp_t *mp, u_char *dst, u_char *src);
|
||||||
|
|
||||||
|
#if (NXT_HAVE_ISOLATION_ROOTFS)
|
||||||
|
static nxt_int_t nxt_app_prepare_rootfs(nxt_task_t *task,
|
||||||
|
nxt_process_t *process);
|
||||||
|
static nxt_int_t nxt_app_prepare_lang_mounts(nxt_task_t *task,
|
||||||
|
nxt_process_t *process, nxt_array_t *syspaths);
|
||||||
|
static nxt_int_t nxt_app_set_isolation_rootfs(nxt_task_t *task,
|
||||||
|
nxt_conf_value_t *isolation, nxt_process_t *process);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static nxt_int_t nxt_app_set_isolation(nxt_task_t *task,
|
||||||
nxt_conf_value_t *isolation, nxt_process_t *process);
|
nxt_conf_value_t *isolation, nxt_process_t *process);
|
||||||
|
|
||||||
#if (NXT_HAVE_CLONE)
|
#if (NXT_HAVE_CLONE)
|
||||||
|
static nxt_int_t nxt_app_set_isolation_namespaces(nxt_task_t *task,
|
||||||
|
nxt_conf_value_t *isolation, nxt_process_t *process);
|
||||||
static nxt_int_t nxt_app_clone_flags(nxt_task_t *task,
|
static nxt_int_t nxt_app_clone_flags(nxt_task_t *task,
|
||||||
nxt_conf_value_t *namespaces, nxt_clone_t *clone);
|
nxt_conf_value_t *namespaces, nxt_clone_t *clone);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if (NXT_HAVE_CLONE_NEWUSER)
|
#if (NXT_HAVE_CLONE_NEWUSER)
|
||||||
static nxt_int_t nxt_app_isolation_creds(nxt_task_t *task,
|
static nxt_int_t nxt_app_set_isolation_creds(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_app_isolation_credential_map(nxt_task_t *task,
|
static nxt_int_t nxt_app_isolation_credential_map(nxt_task_t *task,
|
||||||
nxt_mp_t *mem_pool, nxt_conf_value_t *map_array,
|
nxt_mp_t *mem_pool, nxt_conf_value_t *map_array,
|
||||||
nxt_clone_credential_map_t *map);
|
nxt_clone_credential_map_t *map);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if (NXT_HAVE_PR_SET_NO_NEW_PRIVS)
|
||||||
|
static nxt_int_t nxt_app_set_isolation_new_privs(nxt_task_t *task,
|
||||||
|
nxt_conf_value_t *isolation, nxt_process_t *process);
|
||||||
|
#endif
|
||||||
|
|
||||||
nxt_str_t nxt_server = nxt_string(NXT_SERVER);
|
nxt_str_t nxt_server = nxt_string(NXT_SERVER);
|
||||||
|
|
||||||
|
|
||||||
@@ -154,16 +177,17 @@ nxt_discovery_start(nxt_task_t *task, nxt_process_data_t *data)
|
|||||||
static nxt_buf_t *
|
static nxt_buf_t *
|
||||||
nxt_discovery_modules(nxt_task_t *task, const char *path)
|
nxt_discovery_modules(nxt_task_t *task, const char *path)
|
||||||
{
|
{
|
||||||
char *name;
|
char *name;
|
||||||
u_char *p, *end;
|
u_char *p, *end;
|
||||||
size_t size;
|
size_t size;
|
||||||
glob_t glb;
|
glob_t glb;
|
||||||
nxt_mp_t *mp;
|
nxt_mp_t *mp;
|
||||||
nxt_buf_t *b;
|
nxt_buf_t *b;
|
||||||
nxt_int_t ret;
|
nxt_int_t ret;
|
||||||
nxt_uint_t i, n;
|
nxt_uint_t i, n, j;
|
||||||
nxt_array_t *modules;
|
nxt_array_t *modules, *mounts;
|
||||||
nxt_module_t *module;
|
nxt_module_t *module;
|
||||||
|
nxt_fs_mount_t *mnt;
|
||||||
|
|
||||||
b = NULL;
|
b = NULL;
|
||||||
|
|
||||||
@@ -206,11 +230,26 @@ nxt_discovery_modules(nxt_task_t *task, const char *path)
|
|||||||
|
|
||||||
size += nxt_length("{\"type\": ,");
|
size += nxt_length("{\"type\": ,");
|
||||||
size += nxt_length(" \"version\": \"\",");
|
size += nxt_length(" \"version\": \"\",");
|
||||||
size += nxt_length(" \"file\": \"\"},");
|
size += nxt_length(" \"file\": \"\",");
|
||||||
|
size += nxt_length(" \"mounts\": []},");
|
||||||
|
|
||||||
size += NXT_INT_T_LEN
|
size += NXT_INT_T_LEN
|
||||||
+ module[i].version.length
|
+ module[i].version.length
|
||||||
+ module[i].file.length;
|
+ module[i].file.length;
|
||||||
|
|
||||||
|
mounts = module[i].mounts;
|
||||||
|
|
||||||
|
size += mounts->nelts * nxt_length("{\"src\": \"\", \"dst\": \"\", "
|
||||||
|
"\"fstype\": \"\", \"flags\": , "
|
||||||
|
"\"data\": \"\"},");
|
||||||
|
|
||||||
|
mnt = mounts->elts;
|
||||||
|
|
||||||
|
for (j = 0; j < mounts->nelts; j++) {
|
||||||
|
size += nxt_strlen(mnt[j].src) + nxt_strlen(mnt[j].dst)
|
||||||
|
+ nxt_strlen(mnt[j].fstype) + NXT_INT_T_LEN
|
||||||
|
+ (mnt[j].data == NULL ? 0 : nxt_strlen(mnt[j].data));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
b = nxt_buf_mem_alloc(mp, size, 0);
|
b = nxt_buf_mem_alloc(mp, size, 0);
|
||||||
@@ -225,12 +264,34 @@ nxt_discovery_modules(nxt_task_t *task, const char *path)
|
|||||||
*p++ = '[';
|
*p++ = '[';
|
||||||
|
|
||||||
for (i = 0; i < n; i++) {
|
for (i = 0; i < n; i++) {
|
||||||
p = nxt_sprintf(p, end,
|
mounts = module[i].mounts;
|
||||||
"{\"type\": %d, \"version\": \"%V\", \"file\": \"%V\"},",
|
|
||||||
module[i].type, &module[i].version, &module[i].file);
|
p = nxt_sprintf(p, end, "{\"type\": %d, \"version\": \"%V\", "
|
||||||
|
"\"file\": \"%V\", \"mounts\": [",
|
||||||
|
module[i].type, &module[i].version, &module[i].file);
|
||||||
|
|
||||||
|
mnt = mounts->elts;
|
||||||
|
for (j = 0; j < mounts->nelts; j++) {
|
||||||
|
p = nxt_sprintf(p, end,
|
||||||
|
"{\"src\": \"%s\", \"dst\": \"%s\", "
|
||||||
|
"\"fstype\": \"%s\", \"flags\": %d, "
|
||||||
|
"\"data\": \"%s\"},",
|
||||||
|
mnt[j].src, mnt[j].dst, mnt[j].fstype, mnt[j].flags,
|
||||||
|
mnt[j].data == NULL ? (u_char *) "" : mnt[j].data);
|
||||||
|
}
|
||||||
|
|
||||||
|
*p++ = ']';
|
||||||
|
*p++ = '}';
|
||||||
|
*p++ = ',';
|
||||||
}
|
}
|
||||||
|
|
||||||
*p++ = ']';
|
*p++ = ']';
|
||||||
|
|
||||||
|
if (nxt_slow_path(p >= end)) {
|
||||||
|
nxt_alert(task, "discovery write past the buffer");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
b->mem.free = p;
|
b->mem.free = p;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
@@ -245,13 +306,16 @@ static nxt_int_t
|
|||||||
nxt_discovery_module(nxt_task_t *task, nxt_mp_t *mp, nxt_array_t *modules,
|
nxt_discovery_module(nxt_task_t *task, nxt_mp_t *mp, nxt_array_t *modules,
|
||||||
const char *name)
|
const char *name)
|
||||||
{
|
{
|
||||||
void *dl;
|
void *dl;
|
||||||
nxt_str_t version;
|
nxt_str_t version;
|
||||||
nxt_int_t ret;
|
nxt_int_t ret;
|
||||||
nxt_uint_t i, n;
|
nxt_uint_t i, j, n;
|
||||||
nxt_module_t *module;
|
nxt_array_t *mounts;
|
||||||
nxt_app_type_t type;
|
nxt_module_t *module;
|
||||||
nxt_app_module_t *app;
|
nxt_app_type_t type;
|
||||||
|
nxt_fs_mount_t *to;
|
||||||
|
nxt_app_module_t *app;
|
||||||
|
const nxt_fs_mount_t *from;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Only memory allocation failure should return NXT_ERROR.
|
* Only memory allocation failure should return NXT_ERROR.
|
||||||
@@ -328,6 +392,47 @@ nxt_discovery_module(nxt_task_t *task, nxt_mp_t *mp, nxt_array_t *modules,
|
|||||||
|
|
||||||
nxt_memcpy(module->file.start, name, module->file.length);
|
nxt_memcpy(module->file.start, name, module->file.length);
|
||||||
|
|
||||||
|
module->mounts = nxt_array_create(mp, app->nmounts,
|
||||||
|
sizeof(nxt_fs_mount_t));
|
||||||
|
|
||||||
|
if (nxt_slow_path(module->mounts == NULL)) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
mounts = module->mounts;
|
||||||
|
|
||||||
|
for (j = 0; j < app->nmounts; j++) {
|
||||||
|
from = &app->mounts[j];
|
||||||
|
to = nxt_array_zero_add(mounts);
|
||||||
|
if (nxt_slow_path(to == NULL)) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
to->src = nxt_cstr_dup(mp, to->src, from->src);
|
||||||
|
if (nxt_slow_path(to->src == NULL)) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
to->dst = nxt_cstr_dup(mp, to->dst, from->dst);
|
||||||
|
if (nxt_slow_path(to->dst == NULL)) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
to->fstype = nxt_cstr_dup(mp, to->fstype, from->fstype);
|
||||||
|
if (nxt_slow_path(to->fstype == NULL)) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (from->data != NULL) {
|
||||||
|
to->data = nxt_cstr_dup(mp, to->data, from->data);
|
||||||
|
if (nxt_slow_path(to->data == NULL)) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
to->flags = from->flags;
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
nxt_alert(task, "dlsym(\"%s\"), failed: \"%s\"", name, dlerror());
|
nxt_alert(task, "dlsym(\"%s\"), failed: \"%s\"", name, dlerror());
|
||||||
}
|
}
|
||||||
@@ -369,17 +474,23 @@ nxt_discovery_quit(nxt_task_t *task, nxt_port_recv_msg_t *msg, void *data)
|
|||||||
static nxt_int_t
|
static nxt_int_t
|
||||||
nxt_app_prefork(nxt_task_t *task, nxt_process_t *process, nxt_mp_t *mp)
|
nxt_app_prefork(nxt_task_t *task, nxt_process_t *process, nxt_mp_t *mp)
|
||||||
{
|
{
|
||||||
nxt_int_t cap_setid;
|
nxt_int_t cap_setid, cap_chroot;
|
||||||
nxt_int_t ret;
|
nxt_int_t ret;
|
||||||
nxt_runtime_t *rt;
|
nxt_runtime_t *rt;
|
||||||
nxt_common_app_conf_t *app_conf;
|
nxt_common_app_conf_t *app_conf;
|
||||||
|
nxt_app_lang_module_t *lang;
|
||||||
|
|
||||||
rt = task->thread->runtime;
|
rt = task->thread->runtime;
|
||||||
app_conf = process->data.app;
|
app_conf = process->data.app;
|
||||||
cap_setid = rt->capabilities.setid;
|
cap_setid = rt->capabilities.setid;
|
||||||
|
cap_chroot = rt->capabilities.chroot;
|
||||||
|
|
||||||
|
lang = nxt_app_lang_module(rt, &app_conf->type);
|
||||||
|
|
||||||
|
nxt_assert(lang != NULL);
|
||||||
|
|
||||||
if (app_conf->isolation != NULL) {
|
if (app_conf->isolation != NULL) {
|
||||||
ret = nxt_app_isolation(task, app_conf->isolation, process);
|
ret = nxt_app_set_isolation(task, app_conf->isolation, process);
|
||||||
if (nxt_slow_path(ret != NXT_OK)) {
|
if (nxt_slow_path(ret != NXT_OK)) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -388,6 +499,25 @@ nxt_app_prefork(nxt_task_t *task, nxt_process_t *process, nxt_mp_t *mp)
|
|||||||
#if (NXT_HAVE_CLONE_NEWUSER)
|
#if (NXT_HAVE_CLONE_NEWUSER)
|
||||||
if (nxt_is_clone_flag_set(process->isolation.clone.flags, NEWUSER)) {
|
if (nxt_is_clone_flag_set(process->isolation.clone.flags, NEWUSER)) {
|
||||||
cap_setid = 1;
|
cap_setid = 1;
|
||||||
|
cap_chroot = 1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if (NXT_HAVE_ISOLATION_ROOTFS)
|
||||||
|
if (process->isolation.rootfs != NULL) {
|
||||||
|
if (!cap_chroot) {
|
||||||
|
nxt_log(task, NXT_LOG_ERR,
|
||||||
|
"The \"rootfs\" field requires privileges");
|
||||||
|
|
||||||
|
return NXT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lang->mounts != NULL && lang->mounts->nelts > 0) {
|
||||||
|
ret = nxt_app_prepare_lang_mounts(task, process, lang->mounts);
|
||||||
|
if (nxt_slow_path(ret != NXT_OK)) {
|
||||||
|
return NXT_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -460,6 +590,13 @@ nxt_app_setup(nxt_task_t *task, nxt_process_t *process)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (nxt_slow_path(nxt_app_set_environment(app_conf->environment)
|
||||||
|
!= NXT_OK))
|
||||||
|
{
|
||||||
|
nxt_alert(task, "failed to set environment");
|
||||||
|
return NXT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
if (nxt_app->setup != NULL) {
|
if (nxt_app->setup != NULL) {
|
||||||
ret = nxt_app->setup(task, process, app_conf);
|
ret = nxt_app->setup(task, process, app_conf);
|
||||||
|
|
||||||
@@ -468,6 +605,22 @@ nxt_app_setup(nxt_task_t *task, nxt_process_t *process)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if (NXT_HAVE_ISOLATION_ROOTFS)
|
||||||
|
if (process->isolation.rootfs != NULL) {
|
||||||
|
if (process->isolation.mounts != NULL) {
|
||||||
|
ret = nxt_app_prepare_rootfs(task, process);
|
||||||
|
if (nxt_slow_path(ret != NXT_OK)) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = nxt_process_change_root(task, process);
|
||||||
|
if (nxt_slow_path(ret != NXT_OK)) {
|
||||||
|
return NXT_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
if (app_conf->working_directory != NULL
|
if (app_conf->working_directory != NULL
|
||||||
&& app_conf->working_directory[0] != 0)
|
&& app_conf->working_directory[0] != 0)
|
||||||
{
|
{
|
||||||
@@ -481,13 +634,6 @@ nxt_app_setup(nxt_task_t *task, nxt_process_t *process)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nxt_slow_path(nxt_app_set_environment(app_conf->environment)
|
|
||||||
!= NXT_OK))
|
|
||||||
{
|
|
||||||
nxt_alert(task, "failed to set environment");
|
|
||||||
return NXT_ERROR;
|
|
||||||
}
|
|
||||||
|
|
||||||
init = nxt_process_init(process);
|
init = nxt_process_init(process);
|
||||||
|
|
||||||
init->start = nxt_app->start;
|
init->start = nxt_app->start;
|
||||||
@@ -555,10 +701,51 @@ nxt_app_set_environment(nxt_conf_value_t *environment)
|
|||||||
|
|
||||||
|
|
||||||
static nxt_int_t
|
static nxt_int_t
|
||||||
nxt_app_isolation(nxt_task_t *task, nxt_conf_value_t *isolation,
|
nxt_app_set_isolation(nxt_task_t *task, nxt_conf_value_t *isolation,
|
||||||
nxt_process_t *process)
|
nxt_process_t *process)
|
||||||
{
|
{
|
||||||
#if (NXT_HAVE_CLONE)
|
#if (NXT_HAVE_CLONE)
|
||||||
|
if (nxt_slow_path(nxt_app_set_isolation_namespaces(task, isolation, process)
|
||||||
|
!= NXT_OK))
|
||||||
|
{
|
||||||
|
return NXT_ERROR;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if (NXT_HAVE_CLONE_NEWUSER)
|
||||||
|
if (nxt_slow_path(nxt_app_set_isolation_creds(task, isolation, process)
|
||||||
|
!= NXT_OK))
|
||||||
|
{
|
||||||
|
return NXT_ERROR;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if (NXT_HAVE_ISOLATION_ROOTFS)
|
||||||
|
if (nxt_slow_path(nxt_app_set_isolation_rootfs(task, isolation, process)
|
||||||
|
!= NXT_OK))
|
||||||
|
{
|
||||||
|
return NXT_ERROR;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if (NXT_HAVE_PR_SET_NO_NEW_PRIVS)
|
||||||
|
if (nxt_slow_path(nxt_app_set_isolation_new_privs(task, isolation, process)
|
||||||
|
!= NXT_OK))
|
||||||
|
{
|
||||||
|
return NXT_ERROR;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return NXT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if (NXT_HAVE_CLONE)
|
||||||
|
|
||||||
|
static nxt_int_t
|
||||||
|
nxt_app_set_isolation_namespaces(nxt_task_t *task, nxt_conf_value_t *isolation,
|
||||||
|
nxt_process_t *process)
|
||||||
|
{
|
||||||
nxt_int_t ret;
|
nxt_int_t ret;
|
||||||
nxt_conf_value_t *obj;
|
nxt_conf_value_t *obj;
|
||||||
|
|
||||||
@@ -571,23 +758,82 @@ nxt_app_isolation(nxt_task_t *task, nxt_conf_value_t *isolation,
|
|||||||
return NXT_ERROR;
|
return NXT_ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
#if (NXT_HAVE_CLONE_NEWUSER)
|
|
||||||
ret = nxt_app_isolation_creds(task, isolation, process);
|
|
||||||
if (nxt_slow_path(ret != NXT_OK)) {
|
|
||||||
return NXT_ERROR;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return NXT_OK;
|
return NXT_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#if (NXT_HAVE_ISOLATION_ROOTFS)
|
||||||
|
|
||||||
|
static nxt_int_t
|
||||||
|
nxt_app_set_isolation_rootfs(nxt_task_t *task, nxt_conf_value_t *isolation,
|
||||||
|
nxt_process_t *process)
|
||||||
|
{
|
||||||
|
nxt_str_t str;
|
||||||
|
nxt_conf_value_t *obj;
|
||||||
|
|
||||||
|
static nxt_str_t rootfs_name = nxt_string("rootfs");
|
||||||
|
|
||||||
|
obj = nxt_conf_get_object_member(isolation, &rootfs_name, NULL);
|
||||||
|
if (obj != NULL) {
|
||||||
|
nxt_conf_get_string(obj, &str);
|
||||||
|
|
||||||
|
if (nxt_slow_path(str.length <= 1 || str.start[0] != '/')) {
|
||||||
|
nxt_log(task, NXT_LOG_ERR, "rootfs requires an absolute path other "
|
||||||
|
"than \"/\" but given \"%V\"", &str);
|
||||||
|
|
||||||
|
return NXT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (str.start[str.length - 1] == '/') {
|
||||||
|
str.length--;
|
||||||
|
}
|
||||||
|
|
||||||
|
process->isolation.rootfs = nxt_mp_alloc(process->mem_pool,
|
||||||
|
str.length + 1);
|
||||||
|
|
||||||
|
if (nxt_slow_path(process->isolation.rootfs == NULL)) {
|
||||||
|
return NXT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
nxt_memcpy(process->isolation.rootfs, str.start, str.length);
|
||||||
|
|
||||||
|
process->isolation.rootfs[str.length] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
return NXT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#if (NXT_HAVE_PR_SET_NO_NEW_PRIVS)
|
||||||
|
|
||||||
|
static nxt_int_t
|
||||||
|
nxt_app_set_isolation_new_privs(nxt_task_t *task, nxt_conf_value_t *isolation,
|
||||||
|
nxt_process_t *process)
|
||||||
|
{
|
||||||
|
nxt_conf_value_t *obj;
|
||||||
|
|
||||||
|
static nxt_str_t new_privs_name = nxt_string("new_privs");
|
||||||
|
|
||||||
|
obj = nxt_conf_get_object_member(isolation, &new_privs_name, NULL);
|
||||||
|
if (obj != NULL) {
|
||||||
|
process->isolation.new_privs = nxt_conf_get_boolean(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NXT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#if (NXT_HAVE_CLONE_NEWUSER)
|
#if (NXT_HAVE_CLONE_NEWUSER)
|
||||||
|
|
||||||
static nxt_int_t
|
static nxt_int_t
|
||||||
nxt_app_isolation_creds(nxt_task_t *task, nxt_conf_value_t *isolation,
|
nxt_app_set_isolation_creds(nxt_task_t *task, nxt_conf_value_t *isolation,
|
||||||
nxt_process_t *process)
|
nxt_process_t *process)
|
||||||
{
|
{
|
||||||
nxt_int_t ret;
|
nxt_int_t ret;
|
||||||
@@ -753,6 +999,165 @@ nxt_app_clone_flags(nxt_task_t *task, nxt_conf_value_t *namespaces,
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#if (NXT_HAVE_ISOLATION_ROOTFS)
|
||||||
|
|
||||||
|
static nxt_int_t
|
||||||
|
nxt_app_prepare_lang_mounts(nxt_task_t *task, nxt_process_t *process,
|
||||||
|
nxt_array_t *lang_mounts)
|
||||||
|
{
|
||||||
|
u_char *p;
|
||||||
|
size_t i, n, rootfs_len, len;
|
||||||
|
nxt_mp_t *mp;
|
||||||
|
nxt_array_t *mounts;
|
||||||
|
const u_char *rootfs;
|
||||||
|
nxt_fs_mount_t *mnt, *lang_mnt;
|
||||||
|
|
||||||
|
rootfs = process->isolation.rootfs;
|
||||||
|
rootfs_len = nxt_strlen(rootfs);
|
||||||
|
mp = process->mem_pool;
|
||||||
|
|
||||||
|
/* copy to init mem pool */
|
||||||
|
mounts = nxt_array_copy(mp, NULL, lang_mounts);
|
||||||
|
if (mounts == NULL) {
|
||||||
|
return NXT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
n = mounts->nelts;
|
||||||
|
mnt = mounts->elts;
|
||||||
|
lang_mnt = lang_mounts->elts;
|
||||||
|
|
||||||
|
for (i = 0; i < n; i++) {
|
||||||
|
len = nxt_strlen(lang_mnt[i].dst);
|
||||||
|
|
||||||
|
mnt[i].dst = nxt_mp_alloc(mp, rootfs_len + len + 1);
|
||||||
|
if (mnt[i].dst == NULL) {
|
||||||
|
return NXT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
p = nxt_cpymem(mnt[i].dst, rootfs, rootfs_len);
|
||||||
|
p = nxt_cpymem(p, lang_mnt[i].dst, len);
|
||||||
|
*p = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
process->isolation.mounts = mounts;
|
||||||
|
|
||||||
|
return NXT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static nxt_int_t
|
||||||
|
nxt_app_prepare_rootfs(nxt_task_t *task, nxt_process_t *process)
|
||||||
|
{
|
||||||
|
size_t i, n;
|
||||||
|
nxt_int_t ret, hasproc;
|
||||||
|
struct stat st;
|
||||||
|
nxt_array_t *mounts;
|
||||||
|
const u_char *dst;
|
||||||
|
nxt_fs_mount_t *mnt;
|
||||||
|
|
||||||
|
hasproc = 0;
|
||||||
|
|
||||||
|
#if (NXT_HAVE_CLONE_NEWPID) && (NXT_HAVE_CLONE_NEWNS)
|
||||||
|
nxt_fs_mount_t mount;
|
||||||
|
|
||||||
|
if (nxt_is_clone_flag_set(process->isolation.clone.flags, NEWPID)
|
||||||
|
&& nxt_is_clone_flag_set(process->isolation.clone.flags, NEWNS))
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* This mount point will automatically be gone when the namespace is
|
||||||
|
* destroyed.
|
||||||
|
*/
|
||||||
|
|
||||||
|
mount.fstype = (u_char *) "proc";
|
||||||
|
mount.src = (u_char *) "proc";
|
||||||
|
mount.dst = (u_char *) "/proc";
|
||||||
|
mount.data = (u_char *) "";
|
||||||
|
mount.flags = 0;
|
||||||
|
|
||||||
|
ret = nxt_fs_mkdir_all(mount.dst, S_IRWXU | S_IRWXG | S_IRWXO);
|
||||||
|
if (nxt_fast_path(ret == NXT_OK)) {
|
||||||
|
ret = nxt_fs_mount(task, &mount);
|
||||||
|
if (nxt_fast_path(ret == NXT_OK)) {
|
||||||
|
hasproc = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
nxt_log(task, NXT_LOG_WARN, "mkdir(%s) %E", mount.dst, nxt_errno);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
mounts = process->isolation.mounts;
|
||||||
|
|
||||||
|
n = mounts->nelts;
|
||||||
|
mnt = mounts->elts;
|
||||||
|
|
||||||
|
for (i = 0; i < n; i++) {
|
||||||
|
dst = mnt[i].dst;
|
||||||
|
|
||||||
|
if (nxt_slow_path(nxt_memcmp(mnt[i].fstype, "bind", 4) == 0
|
||||||
|
&& stat((const char *) mnt[i].src, &st) != 0))
|
||||||
|
{
|
||||||
|
nxt_log(task, NXT_LOG_WARN, "host path not found: %s", mnt[i].src);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasproc && nxt_memcmp(mnt[i].fstype, "proc", 4) == 0
|
||||||
|
&& nxt_memcmp(mnt[i].dst, "/proc", 5) == 0)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = nxt_fs_mkdir_all(dst, S_IRWXU | S_IRWXG | S_IRWXO);
|
||||||
|
if (nxt_slow_path(ret != NXT_OK)) {
|
||||||
|
nxt_alert(task, "mkdir(%s) %E", dst, nxt_errno);
|
||||||
|
goto undo;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = nxt_fs_mount(task, &mnt[i]);
|
||||||
|
if (nxt_slow_path(ret != NXT_OK)) {
|
||||||
|
goto undo;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return NXT_OK;
|
||||||
|
|
||||||
|
undo:
|
||||||
|
|
||||||
|
n = i + 1;
|
||||||
|
|
||||||
|
for (i = 0; i < n; i++) {
|
||||||
|
nxt_fs_unmount(mnt[i].dst);
|
||||||
|
}
|
||||||
|
|
||||||
|
return NXT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
static u_char *
|
||||||
|
nxt_cstr_dup(nxt_mp_t *mp, u_char *dst, u_char *src)
|
||||||
|
{
|
||||||
|
u_char *p;
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
len = nxt_strlen(src);
|
||||||
|
|
||||||
|
if (dst == NULL) {
|
||||||
|
dst = nxt_mp_alloc(mp, len + 1);
|
||||||
|
if (nxt_slow_path(dst == NULL)) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
p = nxt_cpymem(dst, src, len);
|
||||||
|
*p = '\0';
|
||||||
|
|
||||||
|
return dst;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
nxt_app_lang_module_t *
|
nxt_app_lang_module_t *
|
||||||
nxt_app_lang_module(nxt_runtime_t *rt, nxt_str_t *name)
|
nxt_app_lang_module(nxt_runtime_t *rt, nxt_str_t *name)
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ typedef struct {
|
|||||||
u_char *version;
|
u_char *version;
|
||||||
char *file;
|
char *file;
|
||||||
nxt_app_module_t *module;
|
nxt_app_module_t *module;
|
||||||
|
nxt_array_t *mounts; /* of nxt_fs_mount_t */
|
||||||
} nxt_app_lang_module_t;
|
} nxt_app_lang_module_t;
|
||||||
|
|
||||||
|
|
||||||
@@ -110,6 +111,9 @@ struct nxt_app_module_s {
|
|||||||
nxt_str_t type;
|
nxt_str_t type;
|
||||||
const char *version;
|
const char *version;
|
||||||
|
|
||||||
|
const nxt_fs_mount_t *mounts;
|
||||||
|
nxt_uint_t nmounts;
|
||||||
|
|
||||||
nxt_application_setup_t setup;
|
nxt_application_setup_t setup;
|
||||||
nxt_process_start_t start;
|
nxt_process_start_t start;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -109,3 +109,42 @@ nxt_array_remove(nxt_array_t *array, void *elt)
|
|||||||
|
|
||||||
array->nelts--;
|
array->nelts--;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
nxt_array_t *
|
||||||
|
nxt_array_copy(nxt_mp_t *mp, nxt_array_t *dst, nxt_array_t *src)
|
||||||
|
{
|
||||||
|
void *data;
|
||||||
|
uint32_t i, size;
|
||||||
|
|
||||||
|
size = src->size;
|
||||||
|
|
||||||
|
if (dst == NULL) {
|
||||||
|
dst = nxt_array_create(mp, src->nelts, size);
|
||||||
|
if (nxt_slow_path(dst == NULL)) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nxt_assert(size == dst->size);
|
||||||
|
|
||||||
|
if (dst->nalloc >= src->nelts) {
|
||||||
|
nxt_memcpy(dst->elts, src->elts, src->nelts * size);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
nxt_memcpy(dst->elts, src->elts, dst->nelts * size);
|
||||||
|
|
||||||
|
for (i = dst->nelts; i < src->nelts; i++) {
|
||||||
|
data = nxt_array_add(dst);
|
||||||
|
if (nxt_slow_path(data == NULL)) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
nxt_memcpy(data, src->elts + (i * size), size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dst->nelts = src->nelts;
|
||||||
|
|
||||||
|
return dst;
|
||||||
|
}
|
||||||
|
|||||||
@@ -24,7 +24,8 @@ NXT_EXPORT void nxt_array_destroy(nxt_array_t *array);
|
|||||||
NXT_EXPORT void *nxt_array_add(nxt_array_t *array);
|
NXT_EXPORT void *nxt_array_add(nxt_array_t *array);
|
||||||
NXT_EXPORT void *nxt_array_zero_add(nxt_array_t *array);
|
NXT_EXPORT void *nxt_array_zero_add(nxt_array_t *array);
|
||||||
NXT_EXPORT void nxt_array_remove(nxt_array_t *array, void *elt);
|
NXT_EXPORT void nxt_array_remove(nxt_array_t *array, void *elt);
|
||||||
|
NXT_EXPORT nxt_array_t *nxt_array_copy(nxt_mp_t *mp, nxt_array_t *dst,
|
||||||
|
nxt_array_t *src);
|
||||||
|
|
||||||
#define \
|
#define \
|
||||||
nxt_array_last(array) \
|
nxt_array_last(array) \
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ nxt_capability_set(nxt_task_t *task, nxt_capabilities_t *cap)
|
|||||||
|
|
||||||
if (geteuid() == 0) {
|
if (geteuid() == 0) {
|
||||||
cap->setid = 1;
|
cap->setid = 1;
|
||||||
|
cap->chroot = 1;
|
||||||
return NXT_OK;
|
return NXT_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -91,6 +92,10 @@ nxt_capability_specific_set(nxt_task_t *task, nxt_capabilities_t *cap)
|
|||||||
return NXT_ERROR;
|
return NXT_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((val->effective & (1 << CAP_SYS_CHROOT)) != 0) {
|
||||||
|
cap->chroot = 1;
|
||||||
|
}
|
||||||
|
|
||||||
if ((val->effective & (1 << CAP_SETUID)) == 0) {
|
if ((val->effective & (1 << CAP_SETUID)) == 0) {
|
||||||
return NXT_OK;
|
return NXT_OK;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,8 @@
|
|||||||
#define _NXT_CAPABILITY_INCLUDED_
|
#define _NXT_CAPABILITY_INCLUDED_
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint8_t setid; /* 1 bit */
|
uint8_t setid; /* 1 bit */
|
||||||
|
uint8_t chroot; /* 1 bit */
|
||||||
} nxt_capabilities_t;
|
} nxt_capabilities_t;
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -42,6 +42,9 @@ pid_t nxt_clone(nxt_int_t flags);
|
|||||||
|
|
||||||
#if (NXT_HAVE_CLONE_NEWUSER)
|
#if (NXT_HAVE_CLONE_NEWUSER)
|
||||||
|
|
||||||
|
#define NXT_CLONE_MNT(flags) \
|
||||||
|
((flags & CLONE_NEWNS) == CLONE_NEWNS)
|
||||||
|
|
||||||
NXT_EXPORT nxt_int_t nxt_clone_credential_map(nxt_task_t *task, pid_t pid,
|
NXT_EXPORT nxt_int_t nxt_clone_credential_map(nxt_task_t *task, pid_t pid,
|
||||||
nxt_credential_t *creds, nxt_clone_t *clone);
|
nxt_credential_t *creds, nxt_clone_t *clone);
|
||||||
NXT_EXPORT nxt_int_t nxt_clone_vldt_credential_uidmap(nxt_task_t *task,
|
NXT_EXPORT nxt_int_t nxt_clone_vldt_credential_uidmap(nxt_task_t *task,
|
||||||
|
|||||||
@@ -573,6 +573,24 @@ static nxt_conf_vldt_object_t nxt_conf_vldt_app_isolation_members[] = {
|
|||||||
&nxt_conf_vldt_array_iterator,
|
&nxt_conf_vldt_array_iterator,
|
||||||
(void *) &nxt_conf_vldt_clone_gidmap },
|
(void *) &nxt_conf_vldt_clone_gidmap },
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if (NXT_HAVE_ISOLATION_ROOTFS)
|
||||||
|
|
||||||
|
{ nxt_string("rootfs"),
|
||||||
|
NXT_CONF_VLDT_STRING,
|
||||||
|
NULL,
|
||||||
|
NULL },
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if (NXT_HAVE_PR_SET_NO_NEW_PRIVS)
|
||||||
|
|
||||||
|
{ nxt_string("new_privs"),
|
||||||
|
NXT_CONF_VLDT_BOOLEAN,
|
||||||
|
NULL,
|
||||||
|
NULL },
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
NXT_CONF_VLDT_END
|
NXT_CONF_VLDT_END
|
||||||
|
|||||||
@@ -18,6 +18,8 @@ nxt_app_module_t nxt_external_module = {
|
|||||||
nxt_string("external"),
|
nxt_string("external"),
|
||||||
"*",
|
"*",
|
||||||
NULL,
|
NULL,
|
||||||
|
0,
|
||||||
|
NULL,
|
||||||
nxt_external_start,
|
nxt_external_start,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
163
src/nxt_fs.c
Normal file
163
src/nxt_fs.c
Normal file
@@ -0,0 +1,163 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) NGINX, Inc.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <nxt_main.h>
|
||||||
|
|
||||||
|
#if (NXT_HAVE_FREEBSD_NMOUNT)
|
||||||
|
#include <sys/param.h>
|
||||||
|
#include <sys/uio.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
static nxt_int_t nxt_fs_mkdir(const u_char *dir, mode_t mode);
|
||||||
|
|
||||||
|
|
||||||
|
#if (NXT_HAVE_LINUX_MOUNT)
|
||||||
|
|
||||||
|
nxt_int_t
|
||||||
|
nxt_fs_mount(nxt_task_t *task, nxt_fs_mount_t *mnt)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
rc = mount((const char *) mnt->src, (const char *) mnt->dst,
|
||||||
|
(const char *) mnt->fstype, mnt->flags, mnt->data);
|
||||||
|
|
||||||
|
if (nxt_slow_path(rc < 0)) {
|
||||||
|
nxt_alert(task, "mount(\"%s\", \"%s\", \"%s\", %d, \"%s\") %E",
|
||||||
|
mnt->src, mnt->dst, mnt->fstype, mnt->flags, mnt->data,
|
||||||
|
nxt_errno);
|
||||||
|
|
||||||
|
return NXT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NXT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#elif (NXT_HAVE_FREEBSD_NMOUNT)
|
||||||
|
|
||||||
|
nxt_int_t
|
||||||
|
nxt_fs_mount(nxt_task_t *task, nxt_fs_mount_t *mnt)
|
||||||
|
{
|
||||||
|
const char *fstype;
|
||||||
|
uint8_t is_bind, is_proc;
|
||||||
|
struct iovec iov[8];
|
||||||
|
char errmsg[256];
|
||||||
|
|
||||||
|
is_bind = nxt_strncmp(mnt->fstype, "bind", 4) == 0;
|
||||||
|
is_proc = nxt_strncmp(mnt->fstype, "proc", 4) == 0;
|
||||||
|
|
||||||
|
if (nxt_slow_path(!is_bind && !is_proc)) {
|
||||||
|
nxt_alert(task, "mount type \"%s\" not implemented.", mnt->fstype);
|
||||||
|
return NXT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_bind) {
|
||||||
|
fstype = "nullfs";
|
||||||
|
|
||||||
|
} else {
|
||||||
|
fstype = "procfs";
|
||||||
|
}
|
||||||
|
|
||||||
|
iov[0].iov_base = (void *) "fstype";
|
||||||
|
iov[0].iov_len = 7;
|
||||||
|
iov[1].iov_base = (void *) fstype;
|
||||||
|
iov[1].iov_len = strlen(fstype) + 1;
|
||||||
|
iov[2].iov_base = (void *) "fspath";
|
||||||
|
iov[2].iov_len = 7;
|
||||||
|
iov[3].iov_base = (void *) mnt->dst;
|
||||||
|
iov[3].iov_len = nxt_strlen(mnt->dst) + 1;
|
||||||
|
iov[4].iov_base = (void *) "target";
|
||||||
|
iov[4].iov_len = 7;
|
||||||
|
iov[5].iov_base = (void *) mnt->src;
|
||||||
|
iov[5].iov_len = nxt_strlen(mnt->src) + 1;
|
||||||
|
iov[6].iov_base = (void *) "errmsg";
|
||||||
|
iov[6].iov_len = 7;
|
||||||
|
iov[7].iov_base = (void *) errmsg;
|
||||||
|
iov[7].iov_len = sizeof(errmsg);
|
||||||
|
|
||||||
|
if (nxt_slow_path(nmount(iov, 8, 0) < 0)) {
|
||||||
|
nxt_alert(task, "nmount(%p, 8, 0) %s", errmsg);
|
||||||
|
return NXT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NXT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#if (NXT_HAVE_LINUX_UMOUNT2)
|
||||||
|
|
||||||
|
void
|
||||||
|
nxt_fs_unmount(const u_char *path)
|
||||||
|
{
|
||||||
|
if (nxt_slow_path(umount2((const char *) path, MNT_DETACH) < 0)) {
|
||||||
|
nxt_thread_log_error(NXT_LOG_WARN, "umount2(%s, MNT_DETACH) %E",
|
||||||
|
path, nxt_errno);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#elif (NXT_HAVE_UNMOUNT)
|
||||||
|
|
||||||
|
void
|
||||||
|
nxt_fs_unmount(const u_char *path)
|
||||||
|
{
|
||||||
|
if (nxt_slow_path(unmount((const char *) path, MNT_FORCE) < 0)) {
|
||||||
|
nxt_thread_log_error(NXT_LOG_WARN, "unmount(%s) %E", path, nxt_errno);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
nxt_int_t
|
||||||
|
nxt_fs_mkdir_all(const u_char *dir, mode_t mode)
|
||||||
|
{
|
||||||
|
char *start, *end, *dst;
|
||||||
|
size_t dirlen;
|
||||||
|
char path[PATH_MAX];
|
||||||
|
|
||||||
|
dirlen = nxt_strlen(dir);
|
||||||
|
|
||||||
|
nxt_assert(dirlen < PATH_MAX && dirlen > 1 && dir[0] == '/');
|
||||||
|
|
||||||
|
dst = path;
|
||||||
|
start = end = (char *) dir;
|
||||||
|
|
||||||
|
while (*start != '\0') {
|
||||||
|
if (*start == '/') {
|
||||||
|
*dst++ = *start++;
|
||||||
|
}
|
||||||
|
|
||||||
|
end = strchr(start, '/');
|
||||||
|
if (end == NULL) {
|
||||||
|
end = ((char *)dir + dirlen);
|
||||||
|
}
|
||||||
|
|
||||||
|
dst = nxt_cpymem(dst, start, end - start);
|
||||||
|
*dst = '\0';
|
||||||
|
|
||||||
|
if (nxt_slow_path(nxt_fs_mkdir((u_char *) path, mode) != NXT_OK
|
||||||
|
&& nxt_errno != EEXIST))
|
||||||
|
{
|
||||||
|
return NXT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
start = end;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NXT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static nxt_int_t
|
||||||
|
nxt_fs_mkdir(const u_char *dir, mode_t mode)
|
||||||
|
{
|
||||||
|
if (nxt_fast_path(mkdir((const char *) dir, mode) == 0)) {
|
||||||
|
return NXT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NXT_ERROR;
|
||||||
|
}
|
||||||
36
src/nxt_fs.h
Normal file
36
src/nxt_fs.h
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) NGINX, Inc.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _NXT_FS_H_INCLUDED_
|
||||||
|
#define _NXT_FS_H_INCLUDED_
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef MS_BIND
|
||||||
|
#define NXT_MS_BIND MS_BIND
|
||||||
|
#else
|
||||||
|
#define NXT_MS_BIND 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef MS_REC
|
||||||
|
#define NXT_MS_REC MS_BIND
|
||||||
|
#else
|
||||||
|
#define NXT_MS_REC 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
u_char *src;
|
||||||
|
u_char *dst;
|
||||||
|
u_char *fstype;
|
||||||
|
nxt_int_t flags;
|
||||||
|
u_char *data;
|
||||||
|
} nxt_fs_mount_t;
|
||||||
|
|
||||||
|
|
||||||
|
nxt_int_t nxt_fs_mkdir_all(const u_char *dir, mode_t mode);
|
||||||
|
nxt_int_t nxt_fs_mount(nxt_task_t *task, nxt_fs_mount_t *mnt);
|
||||||
|
void nxt_fs_unmount(const u_char *path);
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* _NXT_FS_H_INCLUDED_ */
|
||||||
@@ -26,6 +26,7 @@
|
|||||||
#include "java/nxt_jni_URLClassLoader.h"
|
#include "java/nxt_jni_URLClassLoader.h"
|
||||||
|
|
||||||
#include "nxt_jars.h"
|
#include "nxt_jars.h"
|
||||||
|
#include "nxt_java_mounts.h"
|
||||||
|
|
||||||
static nxt_int_t nxt_java_setup(nxt_task_t *task, nxt_process_t *process,
|
static nxt_int_t nxt_java_setup(nxt_task_t *task, nxt_process_t *process,
|
||||||
nxt_common_app_conf_t *conf);
|
nxt_common_app_conf_t *conf);
|
||||||
@@ -50,6 +51,8 @@ NXT_EXPORT nxt_app_module_t nxt_app_module = {
|
|||||||
compat,
|
compat,
|
||||||
nxt_string("java"),
|
nxt_string("java"),
|
||||||
NXT_STRING(NXT_JAVA_VERSION),
|
NXT_STRING(NXT_JAVA_VERSION),
|
||||||
|
nxt_java_mounts,
|
||||||
|
nxt_nitems(nxt_java_mounts),
|
||||||
nxt_java_setup,
|
nxt_java_setup,
|
||||||
nxt_java_start,
|
nxt_java_start,
|
||||||
};
|
};
|
||||||
@@ -64,20 +67,66 @@ static nxt_int_t
|
|||||||
nxt_java_setup(nxt_task_t *task, nxt_process_t *process,
|
nxt_java_setup(nxt_task_t *task, nxt_process_t *process,
|
||||||
nxt_common_app_conf_t *conf)
|
nxt_common_app_conf_t *conf)
|
||||||
{
|
{
|
||||||
|
char *path, *relpath, *p, *rootfs;
|
||||||
|
size_t jars_dir_len, rootfs_len;
|
||||||
const char *unit_jars;
|
const char *unit_jars;
|
||||||
|
|
||||||
|
rootfs = (char *) process->isolation.rootfs;
|
||||||
|
rootfs_len = 0;
|
||||||
|
|
||||||
unit_jars = conf->u.java.unit_jars;
|
unit_jars = conf->u.java.unit_jars;
|
||||||
if (unit_jars == NULL) {
|
if (unit_jars == NULL) {
|
||||||
unit_jars = NXT_JARS;
|
if (rootfs != NULL) {
|
||||||
|
unit_jars = "/";
|
||||||
|
} else {
|
||||||
|
unit_jars = NXT_JARS;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
nxt_java_modules = realpath(unit_jars, NULL);
|
relpath = strdup(unit_jars);
|
||||||
if (nxt_java_modules == NULL) {
|
if (nxt_slow_path(relpath == NULL)) {
|
||||||
nxt_alert(task, "realpath(%s) failed: %E", unit_jars, nxt_errno);
|
|
||||||
return NXT_ERROR;
|
return NXT_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (rootfs != NULL) {
|
||||||
|
jars_dir_len = strlen(unit_jars);
|
||||||
|
rootfs_len = strlen(rootfs);
|
||||||
|
|
||||||
|
path = nxt_malloc(jars_dir_len + rootfs_len + 1);
|
||||||
|
if (nxt_slow_path(path == NULL)) {
|
||||||
|
free(relpath);
|
||||||
|
return NXT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
p = nxt_cpymem(path, process->isolation.rootfs, rootfs_len);
|
||||||
|
p = nxt_cpymem(p, relpath, jars_dir_len);
|
||||||
|
*p = '\0';
|
||||||
|
|
||||||
|
free(relpath);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
path = relpath;
|
||||||
|
}
|
||||||
|
|
||||||
|
nxt_java_modules = realpath(path, NULL);
|
||||||
|
if (nxt_java_modules == NULL) {
|
||||||
|
nxt_alert(task, "realpath(\"%s\") failed %E", path, nxt_errno);
|
||||||
|
goto free;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rootfs != NULL && strlen(path) > rootfs_len) {
|
||||||
|
nxt_java_modules = path + rootfs_len;
|
||||||
|
}
|
||||||
|
|
||||||
|
nxt_debug(task, "JAVA MODULES: %s", nxt_java_modules);
|
||||||
|
|
||||||
return NXT_OK;
|
return NXT_OK;
|
||||||
|
|
||||||
|
free:
|
||||||
|
|
||||||
|
nxt_free(path);
|
||||||
|
|
||||||
|
return NXT_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -85,6 +134,7 @@ static char **
|
|||||||
nxt_java_module_jars(const char *jars[], int jar_count)
|
nxt_java_module_jars(const char *jars[], int jar_count)
|
||||||
{
|
{
|
||||||
char **res, *jurl;
|
char **res, *jurl;
|
||||||
|
uint8_t pathsep;
|
||||||
nxt_int_t modules_len, jlen, i;
|
nxt_int_t modules_len, jlen, i;
|
||||||
const char **jar;
|
const char **jar;
|
||||||
|
|
||||||
@@ -95,9 +145,13 @@ nxt_java_module_jars(const char *jars[], int jar_count)
|
|||||||
|
|
||||||
modules_len = nxt_strlen(nxt_java_modules);
|
modules_len = nxt_strlen(nxt_java_modules);
|
||||||
|
|
||||||
|
pathsep = nxt_java_modules[modules_len - 1] == '/';
|
||||||
|
|
||||||
for (i = 0, jar = jars; *jar != NULL; jar++) {
|
for (i = 0, jar = jars; *jar != NULL; jar++) {
|
||||||
jlen = nxt_length("file:") + modules_len + nxt_length("/")
|
jlen = nxt_length("file:") + modules_len
|
||||||
+ nxt_strlen(*jar) + 1;
|
+ (!pathsep ? nxt_length("/") : 0)
|
||||||
|
+ nxt_strlen(*jar) + 1;
|
||||||
|
|
||||||
jurl = nxt_malloc(jlen);
|
jurl = nxt_malloc(jlen);
|
||||||
if (jurl == NULL) {
|
if (jurl == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -107,7 +161,11 @@ nxt_java_module_jars(const char *jars[], int jar_count)
|
|||||||
|
|
||||||
jurl = nxt_cpymem(jurl, "file:", nxt_length("file:"));
|
jurl = nxt_cpymem(jurl, "file:", nxt_length("file:"));
|
||||||
jurl = nxt_cpymem(jurl, nxt_java_modules, modules_len);
|
jurl = nxt_cpymem(jurl, nxt_java_modules, modules_len);
|
||||||
*jurl++ = '/';
|
|
||||||
|
if (!pathsep) {
|
||||||
|
*jurl++ = '/';
|
||||||
|
}
|
||||||
|
|
||||||
jurl = nxt_cpymem(jurl, *jar, nxt_strlen(*jar));
|
jurl = nxt_cpymem(jurl, *jar, nxt_strlen(*jar));
|
||||||
*jurl++ = '\0';
|
*jurl++ = '\0';
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -59,6 +59,7 @@ typedef uint16_t nxt_port_id_t;
|
|||||||
#include <nxt_process_type.h>
|
#include <nxt_process_type.h>
|
||||||
#include <nxt_capability.h>
|
#include <nxt_capability.h>
|
||||||
#include <nxt_credential.h>
|
#include <nxt_credential.h>
|
||||||
|
#include <nxt_fs.h>
|
||||||
#include <nxt_process.h>
|
#include <nxt_process.h>
|
||||||
#include <nxt_utf8.h>
|
#include <nxt_utf8.h>
|
||||||
#include <nxt_file_name.h>
|
#include <nxt_file_name.h>
|
||||||
|
|||||||
@@ -14,6 +14,8 @@
|
|||||||
#include <nxt_cert.h>
|
#include <nxt_cert.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <sys/mount.h>
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
nxt_socket_t socket;
|
nxt_socket_t socket;
|
||||||
@@ -869,6 +871,12 @@ nxt_main_cleanup_process(nxt_task_t *task, nxt_pid_t pid)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if (NXT_HAVE_ISOLATION_ROOTFS)
|
||||||
|
if (process->isolation.rootfs != NULL && process->isolation.mounts) {
|
||||||
|
(void) nxt_process_unmount_all(task, process);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
name = process->name;
|
name = process->name;
|
||||||
stream = process->stream;
|
stream = process->stream;
|
||||||
init = *((nxt_process_init_t *) nxt_process_init(process));
|
init = *((nxt_process_init_t *) nxt_process_init(process));
|
||||||
@@ -1132,19 +1140,50 @@ static nxt_conf_map_t nxt_app_lang_module_map[] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static nxt_conf_map_t nxt_app_lang_mounts_map[] = {
|
||||||
|
{
|
||||||
|
nxt_string("src"),
|
||||||
|
NXT_CONF_MAP_CSTRZ,
|
||||||
|
offsetof(nxt_fs_mount_t, src),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
nxt_string("dst"),
|
||||||
|
NXT_CONF_MAP_CSTRZ,
|
||||||
|
offsetof(nxt_fs_mount_t, dst),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
nxt_string("fstype"),
|
||||||
|
NXT_CONF_MAP_CSTRZ,
|
||||||
|
offsetof(nxt_fs_mount_t, fstype),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
nxt_string("flags"),
|
||||||
|
NXT_CONF_MAP_INT,
|
||||||
|
offsetof(nxt_fs_mount_t, flags),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
nxt_string("data"),
|
||||||
|
NXT_CONF_MAP_CSTRZ,
|
||||||
|
offsetof(nxt_fs_mount_t, data),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
nxt_main_port_modules_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg)
|
nxt_main_port_modules_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg)
|
||||||
{
|
{
|
||||||
uint32_t index;
|
uint32_t index, jindex, nmounts;
|
||||||
nxt_mp_t *mp;
|
nxt_mp_t *mp;
|
||||||
nxt_int_t ret;
|
nxt_int_t ret;
|
||||||
nxt_buf_t *b;
|
nxt_buf_t *b;
|
||||||
nxt_port_t *port;
|
nxt_port_t *port;
|
||||||
nxt_runtime_t *rt;
|
nxt_runtime_t *rt;
|
||||||
nxt_conf_value_t *conf, *root, *value;
|
nxt_fs_mount_t *mnt;
|
||||||
|
nxt_conf_value_t *conf, *root, *value, *mounts;
|
||||||
nxt_app_lang_module_t *lang;
|
nxt_app_lang_module_t *lang;
|
||||||
|
|
||||||
static nxt_str_t root_path = nxt_string("/");
|
static nxt_str_t root_path = nxt_string("/");
|
||||||
|
static nxt_str_t mounts_name = nxt_string("mounts");
|
||||||
|
|
||||||
rt = task->thread->runtime;
|
rt = task->thread->runtime;
|
||||||
|
|
||||||
@@ -1201,7 +1240,7 @@ nxt_main_port_modules_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
lang = nxt_array_add(rt->languages);
|
lang = nxt_array_zero_add(rt->languages);
|
||||||
if (lang == NULL) {
|
if (lang == NULL) {
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
@@ -1215,8 +1254,48 @@ nxt_main_port_modules_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg)
|
|||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
nxt_debug(task, "lang %d %s \"%s\"",
|
mounts = nxt_conf_get_object_member(value, &mounts_name, NULL);
|
||||||
lang->type, lang->version, lang->file);
|
if (mounts == NULL) {
|
||||||
|
nxt_alert(task, "missing mounts from discovery message.");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nxt_conf_type(mounts) != NXT_CONF_ARRAY) {
|
||||||
|
nxt_alert(task, "invalid mounts type from discovery message.");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
nmounts = nxt_conf_array_elements_count(mounts);
|
||||||
|
|
||||||
|
lang->mounts = nxt_array_create(rt->mem_pool, nmounts,
|
||||||
|
sizeof(nxt_fs_mount_t));
|
||||||
|
|
||||||
|
if (lang->mounts == NULL) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (jindex = 0; /* */; jindex++) {
|
||||||
|
value = nxt_conf_get_array_element(mounts, jindex);
|
||||||
|
if (value == NULL) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
mnt = nxt_array_zero_add(lang->mounts);
|
||||||
|
if (mnt == NULL) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = nxt_conf_map_object(rt->mem_pool, value,
|
||||||
|
nxt_app_lang_mounts_map,
|
||||||
|
nxt_nitems(nxt_app_lang_mounts_map), mnt);
|
||||||
|
|
||||||
|
if (ret != NXT_OK) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
nxt_debug(task, "lang %d %s \"%s\" (%d mounts)",
|
||||||
|
lang->type, lang->version, lang->file, lang->mounts->nelts);
|
||||||
}
|
}
|
||||||
|
|
||||||
qsort(rt->languages->elts, rt->languages->nelts,
|
qsort(rt->languages->elts, rt->languages->nelts,
|
||||||
|
|||||||
@@ -242,6 +242,8 @@ NXT_EXPORT nxt_app_module_t nxt_app_module = {
|
|||||||
nxt_string("php"),
|
nxt_string("php"),
|
||||||
PHP_VERSION,
|
PHP_VERSION,
|
||||||
NULL,
|
NULL,
|
||||||
|
0,
|
||||||
|
NULL,
|
||||||
nxt_php_start,
|
nxt_php_start,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -13,6 +13,14 @@
|
|||||||
|
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
|
||||||
|
#if (NXT_HAVE_PR_SET_NO_NEW_PRIVS)
|
||||||
|
#include <sys/prctl.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if (NXT_HAVE_PIVOT_ROOT)
|
||||||
|
#include <mntent.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
static nxt_int_t nxt_process_setup(nxt_task_t *task, nxt_process_t *process);
|
static nxt_int_t nxt_process_setup(nxt_task_t *task, nxt_process_t *process);
|
||||||
static nxt_int_t nxt_process_child_fixup(nxt_task_t *task,
|
static nxt_int_t nxt_process_child_fixup(nxt_task_t *task,
|
||||||
nxt_process_t *process);
|
nxt_process_t *process);
|
||||||
@@ -25,6 +33,19 @@ static void nxt_process_created_ok(nxt_task_t *task, nxt_port_recv_msg_t *msg,
|
|||||||
static void nxt_process_created_error(nxt_task_t *task,
|
static void nxt_process_created_error(nxt_task_t *task,
|
||||||
nxt_port_recv_msg_t *msg, void *data);
|
nxt_port_recv_msg_t *msg, void *data);
|
||||||
|
|
||||||
|
#if (NXT_HAVE_ISOLATION_ROOTFS)
|
||||||
|
static nxt_int_t nxt_process_chroot(nxt_task_t *task, const char *path);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if (NXT_HAVE_PIVOT_ROOT)
|
||||||
|
static nxt_int_t nxt_process_pivot_root(nxt_task_t *task, const char *rootfs);
|
||||||
|
static nxt_int_t nxt_process_private_mount(nxt_task_t *task,
|
||||||
|
const char *rootfs);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if (NXT_HAVE_PIVOT_ROOT)
|
||||||
|
static int nxt_pivot_root(const char *new_root, const char *old_root);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* A cached process pid. */
|
/* A cached process pid. */
|
||||||
nxt_pid_t nxt_pid;
|
nxt_pid_t nxt_pid;
|
||||||
@@ -495,10 +516,347 @@ nxt_process_apply_creds(nxt_task_t *task, nxt_process_t *process)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if (NXT_HAVE_PR_SET_NO_NEW_PRIVS)
|
||||||
|
if (nxt_slow_path(process->isolation.new_privs == 0
|
||||||
|
&& prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) != 0))
|
||||||
|
{
|
||||||
|
nxt_alert(task, "failed to set no_new_privs %E", nxt_errno);
|
||||||
|
return NXT_ERROR;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
return NXT_OK;
|
return NXT_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if (NXT_HAVE_ISOLATION_ROOTFS)
|
||||||
|
|
||||||
|
|
||||||
|
#if (NXT_HAVE_PIVOT_ROOT) && (NXT_HAVE_CLONE_NEWNS)
|
||||||
|
|
||||||
|
|
||||||
|
nxt_int_t
|
||||||
|
nxt_process_change_root(nxt_task_t *task, nxt_process_t *process)
|
||||||
|
{
|
||||||
|
char *rootfs;
|
||||||
|
nxt_int_t ret;
|
||||||
|
|
||||||
|
rootfs = (char *) process->isolation.rootfs;
|
||||||
|
|
||||||
|
nxt_debug(task, "change root: %s", rootfs);
|
||||||
|
|
||||||
|
if (NXT_CLONE_MNT(process->isolation.clone.flags)) {
|
||||||
|
ret = nxt_process_pivot_root(task, rootfs);
|
||||||
|
} else {
|
||||||
|
ret = nxt_process_chroot(task, rootfs);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nxt_fast_path(ret == NXT_OK)) {
|
||||||
|
if (nxt_slow_path(chdir("/") < 0)) {
|
||||||
|
nxt_alert(task, "chdir(\"/\") %E", nxt_errno);
|
||||||
|
return NXT_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
|
||||||
|
nxt_int_t
|
||||||
|
nxt_process_change_root(nxt_task_t *task, nxt_process_t *process)
|
||||||
|
{
|
||||||
|
char *rootfs;
|
||||||
|
|
||||||
|
rootfs = (char *) process->isolation.rootfs;
|
||||||
|
|
||||||
|
nxt_debug(task, "change root: %s", rootfs);
|
||||||
|
|
||||||
|
if (nxt_fast_path(nxt_process_chroot(task, rootfs) == NXT_OK)) {
|
||||||
|
if (nxt_slow_path(chdir("/") < 0)) {
|
||||||
|
nxt_alert(task, "chdir(\"/\") %E", nxt_errno);
|
||||||
|
return NXT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NXT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NXT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#if (NXT_HAVE_ISOLATION_ROOTFS)
|
||||||
|
|
||||||
|
static nxt_int_t
|
||||||
|
nxt_process_chroot(nxt_task_t *task, const char *path)
|
||||||
|
{
|
||||||
|
if (nxt_slow_path(chroot(path) < 0)) {
|
||||||
|
nxt_alert(task, "chroot(%s) %E", path, nxt_errno);
|
||||||
|
return NXT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NXT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
nxt_process_unmount_all(nxt_task_t *task, nxt_process_t *process)
|
||||||
|
{
|
||||||
|
size_t i, n;
|
||||||
|
nxt_array_t *mounts;
|
||||||
|
nxt_fs_mount_t *mnt;
|
||||||
|
|
||||||
|
nxt_debug(task, "unmount all (%s)", process->name);
|
||||||
|
|
||||||
|
mounts = process->isolation.mounts;
|
||||||
|
n = mounts->nelts;
|
||||||
|
mnt = mounts->elts;
|
||||||
|
|
||||||
|
for (i = 0; i < n; i++) {
|
||||||
|
nxt_fs_unmount(mnt[i].dst);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#if (NXT_HAVE_PIVOT_ROOT) && (NXT_HAVE_CLONE_NEWNS)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* pivot_root(2) can only be safely used with containers, otherwise it can
|
||||||
|
* umount(2) the global root filesystem and screw up the machine.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static nxt_int_t
|
||||||
|
nxt_process_pivot_root(nxt_task_t *task, const char *path)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* This implementation makes use of a kernel trick that works for ages
|
||||||
|
* and now documented in Linux kernel 5.
|
||||||
|
* https://lore.kernel.org/linux-man/87r24piwhm.fsf@x220.int.ebiederm.org/T/
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (nxt_slow_path(mount("", "/", "", MS_SLAVE|MS_REC, "") != 0)) {
|
||||||
|
nxt_alert(task, "failed to make / a slave mount %E", nxt_errno);
|
||||||
|
return NXT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nxt_slow_path(nxt_process_private_mount(task, path) != NXT_OK)) {
|
||||||
|
return NXT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nxt_slow_path(mount(path, path, "bind", MS_BIND|MS_REC, "") != 0)) {
|
||||||
|
nxt_alert(task, "error bind mounting rootfs %E", nxt_errno);
|
||||||
|
return NXT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nxt_slow_path(chdir(path) != 0)) {
|
||||||
|
nxt_alert(task, "failed to chdir(%s) %E", path, nxt_errno);
|
||||||
|
return NXT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nxt_slow_path(nxt_pivot_root(".", ".") != 0)) {
|
||||||
|
nxt_alert(task, "failed to pivot_root %E", nxt_errno);
|
||||||
|
return NXT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Make oldroot a slave mount to avoid unmounts getting propagated to the
|
||||||
|
* host.
|
||||||
|
*/
|
||||||
|
if (nxt_slow_path(mount("", ".", "", MS_SLAVE | MS_REC, NULL) != 0)) {
|
||||||
|
nxt_alert(task, "failed to bind mount rootfs %E", nxt_errno);
|
||||||
|
return NXT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nxt_slow_path(umount2(".", MNT_DETACH) != 0)) {
|
||||||
|
nxt_alert(task, "failed to umount old root directory %E", nxt_errno);
|
||||||
|
return NXT_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NXT_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static nxt_int_t
|
||||||
|
nxt_process_private_mount(nxt_task_t *task, const char *rootfs)
|
||||||
|
{
|
||||||
|
char *parent_mnt;
|
||||||
|
FILE *procfile;
|
||||||
|
u_char **mounts;
|
||||||
|
size_t len;
|
||||||
|
uint8_t *shared;
|
||||||
|
nxt_int_t ret, index, nmounts;
|
||||||
|
struct mntent *ent;
|
||||||
|
|
||||||
|
static const char *mount_path = "/proc/self/mounts";
|
||||||
|
|
||||||
|
ret = NXT_ERROR;
|
||||||
|
ent = NULL;
|
||||||
|
shared = NULL;
|
||||||
|
procfile = NULL;
|
||||||
|
parent_mnt = NULL;
|
||||||
|
|
||||||
|
nmounts = 256;
|
||||||
|
|
||||||
|
mounts = nxt_malloc(nmounts * sizeof(uintptr_t));
|
||||||
|
if (nxt_slow_path(mounts == NULL)) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
shared = nxt_malloc(nmounts);
|
||||||
|
if (nxt_slow_path(shared == NULL)) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
procfile = setmntent(mount_path, "r");
|
||||||
|
if (nxt_slow_path(procfile == NULL)) {
|
||||||
|
nxt_alert(task, "failed to open %s %E", mount_path, nxt_errno);
|
||||||
|
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
index = 0;
|
||||||
|
|
||||||
|
again:
|
||||||
|
|
||||||
|
for ( ; index < nmounts; index++) {
|
||||||
|
ent = getmntent(procfile);
|
||||||
|
if (ent == NULL) {
|
||||||
|
nmounts = index;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
mounts[index] = (u_char *) strdup(ent->mnt_dir);
|
||||||
|
shared[index] = hasmntopt(ent, "shared") != NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ent != NULL) {
|
||||||
|
/* there are still entries to be read */
|
||||||
|
|
||||||
|
nmounts *= 2;
|
||||||
|
mounts = nxt_realloc(mounts, nmounts);
|
||||||
|
if (nxt_slow_path(mounts == NULL)) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
shared = nxt_realloc(shared, nmounts);
|
||||||
|
if (nxt_slow_path(shared == NULL)) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
goto again;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (index = 0; index < nmounts; index++) {
|
||||||
|
if (nxt_strcmp(mounts[index], rootfs) == 0) {
|
||||||
|
parent_mnt = (char *) rootfs;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parent_mnt == NULL) {
|
||||||
|
len = nxt_strlen(rootfs);
|
||||||
|
|
||||||
|
parent_mnt = nxt_malloc(len + 1);
|
||||||
|
if (parent_mnt == NULL) {
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
nxt_memcpy(parent_mnt, rootfs, len);
|
||||||
|
parent_mnt[len] = '\0';
|
||||||
|
|
||||||
|
if (parent_mnt[len - 1] == '/') {
|
||||||
|
parent_mnt[len - 1] = '\0';
|
||||||
|
len--;
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( ;; ) {
|
||||||
|
for (index = 0; index < nmounts; index++) {
|
||||||
|
if (nxt_strcmp(mounts[index], parent_mnt) == 0) {
|
||||||
|
goto found;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (len == 1 && parent_mnt[0] == '/') {
|
||||||
|
nxt_alert(task, "parent mount not found");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* parent dir */
|
||||||
|
while (parent_mnt[len - 1] != '/' && len > 0) {
|
||||||
|
len--;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nxt_slow_path(len == 0)) {
|
||||||
|
nxt_alert(task, "parent mount not found");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (len == 1) {
|
||||||
|
parent_mnt[len] = '\0'; /* / */
|
||||||
|
} else {
|
||||||
|
parent_mnt[len - 1] = '\0'; /* /<path> */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
found:
|
||||||
|
|
||||||
|
if (shared[index]) {
|
||||||
|
if (nxt_slow_path(mount("", parent_mnt, "", MS_PRIVATE, "") != 0)) {
|
||||||
|
nxt_alert(task, "mount(\"\", \"%s\", MS_PRIVATE) %E", parent_mnt,
|
||||||
|
nxt_errno);
|
||||||
|
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = NXT_OK;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
|
||||||
|
if (procfile != NULL) {
|
||||||
|
endmntent(procfile);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mounts != NULL) {
|
||||||
|
for (index = 0; index < nmounts; index++) {
|
||||||
|
nxt_free(mounts[index]);
|
||||||
|
}
|
||||||
|
|
||||||
|
nxt_free(mounts);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (shared != NULL) {
|
||||||
|
nxt_free(shared);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (parent_mnt != NULL && parent_mnt != rootfs) {
|
||||||
|
nxt_free(parent_mnt);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
nxt_pivot_root(const char *new_root, const char *old_root)
|
||||||
|
{
|
||||||
|
return syscall(__NR_pivot_root, new_root, old_root);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
static nxt_int_t
|
static nxt_int_t
|
||||||
nxt_process_send_ready(nxt_task_t *task, nxt_process_t *process)
|
nxt_process_send_ready(nxt_task_t *task, nxt_process_t *process)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -69,33 +69,42 @@ 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 */
|
||||||
|
|
||||||
|
#if (NXT_HAVE_CLONE)
|
||||||
|
nxt_clone_t clone;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if (NXT_HAVE_PR_SET_NO_NEW_PRIVS)
|
||||||
|
uint8_t new_privs; /* 1 bit */
|
||||||
|
#endif
|
||||||
|
} nxt_process_isolation_t;
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
nxt_pid_t pid;
|
nxt_pid_t pid;
|
||||||
const char *name;
|
const char *name;
|
||||||
nxt_queue_t ports; /* of nxt_port_t */
|
nxt_queue_t ports; /* of nxt_port_t */
|
||||||
nxt_process_state_t state;
|
nxt_process_state_t state;
|
||||||
nxt_bool_t registered;
|
nxt_bool_t registered;
|
||||||
nxt_int_t use_count;
|
nxt_int_t use_count;
|
||||||
|
|
||||||
nxt_port_mmaps_t incoming;
|
nxt_port_mmaps_t incoming;
|
||||||
nxt_port_mmaps_t outgoing;
|
nxt_port_mmaps_t outgoing;
|
||||||
|
|
||||||
nxt_thread_mutex_t cp_mutex;
|
nxt_thread_mutex_t cp_mutex;
|
||||||
nxt_lvlhsh_t connected_ports; /* of nxt_port_t */
|
nxt_lvlhsh_t connected_ports; /* of nxt_port_t */
|
||||||
|
|
||||||
uint32_t stream;
|
uint32_t stream;
|
||||||
|
|
||||||
nxt_mp_t *mem_pool;
|
nxt_mp_t *mem_pool;
|
||||||
nxt_credential_t *user_cred;
|
nxt_credential_t *user_cred;
|
||||||
|
|
||||||
nxt_process_data_t data;
|
nxt_process_data_t data;
|
||||||
|
|
||||||
union {
|
nxt_process_isolation_t isolation;
|
||||||
#if (NXT_HAVE_CLONE)
|
|
||||||
nxt_clone_t clone;
|
|
||||||
#endif
|
|
||||||
} isolation;
|
|
||||||
} nxt_process_t;
|
} nxt_process_t;
|
||||||
|
|
||||||
|
|
||||||
@@ -184,6 +193,12 @@ nxt_int_t nxt_process_vldt_isolation_creds(nxt_task_t *task,
|
|||||||
nxt_process_t *process);
|
nxt_process_t *process);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
nxt_int_t nxt_process_change_root(nxt_task_t *task, nxt_process_t *process);
|
||||||
|
|
||||||
|
#if (NXT_HAVE_ISOLATION_ROOTFS)
|
||||||
|
void nxt_process_unmount_all(nxt_task_t *task, nxt_process_t *process);
|
||||||
|
#endif
|
||||||
|
|
||||||
#if (NXT_HAVE_SETPROCTITLE)
|
#if (NXT_HAVE_SETPROCTITLE)
|
||||||
|
|
||||||
#define nxt_process_title(task, fmt, ...) \
|
#define nxt_process_title(task, fmt, ...) \
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
#include <nxt_unit_field.h>
|
#include <nxt_unit_field.h>
|
||||||
#include <nxt_unit_request.h>
|
#include <nxt_unit_request.h>
|
||||||
#include <nxt_unit_response.h>
|
#include <nxt_unit_response.h>
|
||||||
|
#include <nxt_python_mounts.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* According to "PEP 3333 / A Note On String Types"
|
* According to "PEP 3333 / A Note On String Types"
|
||||||
@@ -38,11 +39,17 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#define _NXT_PYTHON_MOUNTS(major, minor) \
|
||||||
|
nxt_python ## major ## minor ## _mounts
|
||||||
|
|
||||||
|
#define NXT_PYTHON_MOUNTS(major, minor) _NXT_PYTHON_MOUNTS(major, minor)
|
||||||
|
|
||||||
#if PY_MAJOR_VERSION == 3
|
#if PY_MAJOR_VERSION == 3
|
||||||
#define NXT_PYTHON_BYTES_TYPE "bytestring"
|
#define NXT_PYTHON_BYTES_TYPE "bytestring"
|
||||||
|
|
||||||
#define PyString_FromStringAndSize(str, size) \
|
#define PyString_FromStringAndSize(str, size) \
|
||||||
PyUnicode_DecodeLatin1((str), (size), "strict")
|
PyUnicode_DecodeLatin1((str), (size), "strict")
|
||||||
|
|
||||||
#else
|
#else
|
||||||
#define NXT_PYTHON_BYTES_TYPE "string"
|
#define NXT_PYTHON_BYTES_TYPE "string"
|
||||||
|
|
||||||
@@ -116,6 +123,8 @@ NXT_EXPORT nxt_app_module_t nxt_app_module = {
|
|||||||
compat,
|
compat,
|
||||||
nxt_string("python"),
|
nxt_string("python"),
|
||||||
PY_VERSION,
|
PY_VERSION,
|
||||||
|
NXT_PYTHON_MOUNTS(PY_MAJOR_VERSION, PY_MINOR_VERSION),
|
||||||
|
nxt_nitems(NXT_PYTHON_MOUNTS(PY_MAJOR_VERSION, PY_MINOR_VERSION)),
|
||||||
NULL,
|
NULL,
|
||||||
nxt_python_start,
|
nxt_python_start,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -84,6 +84,7 @@ nxt_runtime_create(nxt_task_t *task)
|
|||||||
lang->version = (u_char *) "";
|
lang->version = (u_char *) "";
|
||||||
lang->file = NULL;
|
lang->file = NULL;
|
||||||
lang->module = &nxt_external_module;
|
lang->module = &nxt_external_module;
|
||||||
|
lang->mounts = NULL;
|
||||||
|
|
||||||
listen_sockets = nxt_array_create(mp, 1, sizeof(nxt_listen_socket_t));
|
listen_sockets = nxt_array_create(mp, 1, sizeof(nxt_listen_socket_t));
|
||||||
if (nxt_slow_path(listen_sockets == NULL)) {
|
if (nxt_slow_path(listen_sockets == NULL)) {
|
||||||
|
|||||||
@@ -238,6 +238,9 @@
|
|||||||
#include <sys/random.h> /* getentropy(). */
|
#include <sys/random.h> /* getentropy(). */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if (NXT_HAVE_ISOLATION_ROOTFS)
|
||||||
|
#include <sys/mount.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#if (NXT_TEST_BUILD)
|
#if (NXT_TEST_BUILD)
|
||||||
#include <nxt_test_build.h>
|
#include <nxt_test_build.h>
|
||||||
|
|||||||
@@ -118,6 +118,12 @@ NXT_EXPORT nxt_app_module_t nxt_app_module = {
|
|||||||
nxt_perl_psgi_compat,
|
nxt_perl_psgi_compat,
|
||||||
nxt_string("perl"),
|
nxt_string("perl"),
|
||||||
PERL_VERSION_STRING,
|
PERL_VERSION_STRING,
|
||||||
|
|
||||||
|
#if (NXT_HAVE_ISOLATION_ROOTFS)
|
||||||
|
NULL,
|
||||||
|
0,
|
||||||
|
#endif
|
||||||
|
|
||||||
NULL,
|
NULL,
|
||||||
nxt_perl_psgi_start,
|
nxt_perl_psgi_start,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
#include <nxt_unit.h>
|
#include <nxt_unit.h>
|
||||||
#include <nxt_unit_request.h>
|
#include <nxt_unit_request.h>
|
||||||
|
#include <nxt_ruby_mounts.h>
|
||||||
|
|
||||||
|
|
||||||
#define NXT_RUBY_RACK_API_VERSION_MAJOR 1
|
#define NXT_RUBY_RACK_API_VERSION_MAJOR 1
|
||||||
@@ -78,6 +79,10 @@ NXT_EXPORT nxt_app_module_t nxt_app_module = {
|
|||||||
compat,
|
compat,
|
||||||
nxt_string("ruby"),
|
nxt_string("ruby"),
|
||||||
ruby_version,
|
ruby_version,
|
||||||
|
#if (NXT_HAVE_ISOLATION_ROOTFS)
|
||||||
|
nxt_ruby_mounts,
|
||||||
|
nxt_nitems(nxt_ruby_mounts),
|
||||||
|
#endif
|
||||||
NULL,
|
NULL,
|
||||||
nxt_ruby_start,
|
nxt_ruby_start,
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user