diff options
-rw-r--r-- | auto/modules/php | 30 | ||||
-rw-r--r-- | src/nxt_php_sapi.c | 162 | ||||
-rw-r--r-- | test/test_php_isolation.py | 51 | ||||
-rw-r--r-- | test/test_python_isolation.py | 30 |
4 files changed, 138 insertions, 135 deletions
diff --git a/auto/modules/php b/auto/modules/php index 848fc1bc..41eeb1c3 100644 --- a/auto/modules/php +++ b/auto/modules/php @@ -59,12 +59,6 @@ NXT_PHP_MODULE=${NXT_PHP_MODULE=${NXT_PHP##*/}} NXT_PHP_LIB_PATH=${NXT_PHP_LIB_PATH=} NXT_PHP_LIB_STATIC=${NXT_PHP_LIB_STATIC=no} NXT_PHP_ADDITIONAL_FLAGS= -NXT_PHP_REALPATH=realpath - - -if [ -z `which $NXT_PHP_REALPATH` ]; then - NXT_PHP_REALPATH="readlink -e" -fi $echo "configuring PHP module" @@ -81,12 +75,6 @@ if /bin/sh -c "${NXT_PHP_CONFIG} --version" >> $NXT_AUTOCONF_ERR 2>&1; then NXT_PHP_VERSION="`${NXT_PHP_CONFIG} --version`" NXT_PHP_EXT_DIR="`${NXT_PHP_CONFIG} --extension-dir`" - NXT_PHP_LIBC_DIR="`${CC} --print-file-name=libc.so`" - NXT_PHP_LIBC_DIR="`$NXT_PHP_REALPATH $NXT_PHP_LIBC_DIR`" - NXT_PHP_LIBC_DIR="`dirname $NXT_PHP_LIBC_DIR`" - NXT_PHP_SYSLIB_DIR="`${CC} --print-file-name=libtinfo.so`" - NXT_PHP_SYSLIB_DIR="`$NXT_PHP_REALPATH $NXT_PHP_SYSLIB_DIR`" - NXT_PHP_SYSLIB_DIR="`dirname $NXT_PHP_SYSLIB_DIR`" $echo " + PHP SAPI: [`${NXT_PHP_CONFIG} --php-sapis`]" @@ -228,21 +216,6 @@ if grep ^$NXT_PHP_MODULE: $NXT_MAKEFILE 2>&1 > /dev/null; then fi -NXT_PHP_MOUNTS_HEADER=nxt_${NXT_PHP_MODULE}_mounts.h - -cat << END > $NXT_BUILD_DIR/$NXT_PHP_MOUNTS_HEADER -static const nxt_fs_mount_t nxt_php_mounts[] = { - {(u_char *) "$NXT_PHP_EXT_DIR", (u_char *) "$NXT_PHP_EXT_DIR", - (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 *) "bind", NXT_MS_BIND | NXT_MS_REC, NULL, 1}, - {(u_char *) "$NXT_PHP_SYSLIB_DIR", (u_char *) "$NXT_PHP_SYSLIB_DIR", - (u_char *) "bind", NXT_MS_BIND | NXT_MS_REC, NULL, 1}, -}; - -END - - $echo " + PHP module: ${NXT_PHP_MODULE}.unit.so" . auto/cc/deps @@ -268,8 +241,7 @@ for nxt_src in $NXT_PHP_MODULE_SRCS; do cat << END >> $NXT_MAKEFILE $NXT_BUILD_DIR/$nxt_obj: $nxt_src $NXT_VERSION_H - \$(CC) -c \$(CFLAGS) -DNXT_PHP_MOUNTS_H=\"$NXT_PHP_MOUNTS_HEADER\" \\ - $NXT_PHP_ADDITIONAL_FLAGS \$(NXT_INCS) \\ + \$(CC) -c \$(CFLAGS) $NXT_PHP_ADDITIONAL_FLAGS \$(NXT_INCS) \\ $NXT_PHP_INCLUDE -DNXT_ZEND_SIGNAL_STARTUP=$NXT_ZEND_SIGNAL_STARTUP \\ $nxt_dep_flags \\ -o $NXT_BUILD_DIR/$nxt_obj $nxt_src diff --git a/src/nxt_php_sapi.c b/src/nxt_php_sapi.c index d7e5b476..de329ad7 100644 --- a/src/nxt_php_sapi.c +++ b/src/nxt_php_sapi.c @@ -14,8 +14,6 @@ #include <nxt_unit.h> #include <nxt_unit_request.h> -#include NXT_PHP_MOUNTS_H - #if PHP_VERSION_ID >= 50400 #define NXT_HAVE_PHP_IGNORE_CWD 1 @@ -79,9 +77,13 @@ typedef void (*zif_handler)(INTERNAL_FUNCTION_PARAMETERS); #endif +static nxt_int_t nxt_php_setup(nxt_task_t *task, nxt_process_t *process, + nxt_common_app_conf_t *conf); static nxt_int_t nxt_php_start(nxt_task_t *task, nxt_process_data_t *data); static nxt_int_t nxt_php_set_target(nxt_task_t *task, nxt_php_target_t *target, nxt_conf_value_t *conf); +static nxt_int_t nxt_php_set_ini_path(nxt_task_t *task, nxt_str_t *path, + char *workdir); static void nxt_php_set_options(nxt_task_t *task, nxt_conf_value_t *options, int type); static nxt_int_t nxt_php_alter_option(nxt_str_t *name, nxt_str_t *value, @@ -252,9 +254,9 @@ NXT_EXPORT nxt_app_module_t nxt_app_module = { compat, nxt_string("php"), PHP_VERSION, - nxt_php_mounts, - nxt_nitems(nxt_php_mounts), NULL, + 0, + nxt_php_setup, nxt_php_start, }; @@ -269,55 +271,20 @@ static void ***tsrm_ls; static nxt_int_t -nxt_php_start(nxt_task_t *task, nxt_process_data_t *data) +nxt_php_setup(nxt_task_t *task, nxt_process_t *process, + nxt_common_app_conf_t *conf) { - u_char *p; - uint32_t next; - nxt_str_t ini_path, name; - nxt_int_t ret; - nxt_uint_t n; - nxt_unit_ctx_t *unit_ctx; - nxt_unit_init_t php_init; - nxt_conf_value_t *value; - nxt_php_app_conf_t *c; - nxt_common_app_conf_t *conf; + nxt_str_t ini_path; + nxt_int_t ret; + nxt_conf_value_t *value; + nxt_php_app_conf_t *c; static nxt_str_t file_str = nxt_string("file"); static nxt_str_t user_str = nxt_string("user"); static nxt_str_t admin_str = nxt_string("admin"); - conf = data->app; c = &conf->u.php; - n = (c->targets != NULL) ? nxt_conf_object_members_count(c->targets) : 1; - - nxt_php_targets = nxt_zalloc(sizeof(nxt_php_target_t) * n); - if (nxt_slow_path(nxt_php_targets == NULL)) { - return NXT_ERROR; - } - - if (c->targets != NULL) { - next = 0; - - for (n = 0; /* void */; n++) { - value = nxt_conf_next_object_member(c->targets, &name, &next); - if (value == NULL) { - break; - } - - ret = nxt_php_set_target(task, &nxt_php_targets[n], value); - if (nxt_slow_path(ret != NXT_OK)) { - return NXT_ERROR; - } - } - - } else { - ret = nxt_php_set_target(task, &nxt_php_targets[0], conf->self); - if (nxt_slow_path(ret != NXT_OK)) { - return NXT_ERROR; - } - } - #ifdef ZTS #if PHP_VERSION_ID >= 70400 @@ -347,15 +314,12 @@ nxt_php_start(nxt_task_t *task, nxt_process_data_t *data) if (value != NULL) { nxt_conf_get_string(value, &ini_path); - p = nxt_malloc(ini_path.length + 1); - if (nxt_slow_path(p == NULL)) { + ret = nxt_php_set_ini_path(task, &ini_path, + conf->working_directory); + + if (nxt_slow_path(ret != NXT_OK)) { return NXT_ERROR; } - - nxt_php_sapi_module.php_ini_path_override = (char *) p; - - p = nxt_cpymem(p, ini_path.start, ini_path.length); - *p = '\0'; } } @@ -372,6 +336,55 @@ nxt_php_start(nxt_task_t *task, nxt_process_data_t *data) nxt_php_set_options(task, value, ZEND_INI_USER); } + return NXT_OK; +} + + +static nxt_int_t +nxt_php_start(nxt_task_t *task, nxt_process_data_t *data) +{ + uint32_t next; + nxt_int_t ret; + nxt_str_t name; + nxt_uint_t n; + nxt_unit_ctx_t *unit_ctx; + nxt_unit_init_t php_init; + nxt_conf_value_t *value; + nxt_php_app_conf_t *c; + nxt_common_app_conf_t *conf; + + conf = data->app; + c = &conf->u.php; + + n = (c->targets != NULL) ? nxt_conf_object_members_count(c->targets) : 1; + + nxt_php_targets = nxt_zalloc(sizeof(nxt_php_target_t) * n); + if (nxt_slow_path(nxt_php_targets == NULL)) { + return NXT_ERROR; + } + + if (c->targets != NULL) { + next = 0; + + for (n = 0; /* void */; n++) { + value = nxt_conf_next_object_member(c->targets, &name, &next); + if (value == NULL) { + break; + } + + ret = nxt_php_set_target(task, &nxt_php_targets[n], value); + if (nxt_slow_path(ret != NXT_OK)) { + return NXT_ERROR; + } + } + + } else { + ret = nxt_php_set_target(task, &nxt_php_targets[0], conf->self); + if (nxt_slow_path(ret != NXT_OK)) { + return NXT_ERROR; + } + } + ret = nxt_unit_default_init(task, &php_init); if (nxt_slow_path(ret != NXT_OK)) { nxt_alert(task, "nxt_unit_default_init() failed"); @@ -388,9 +401,8 @@ nxt_php_start(nxt_task_t *task, nxt_process_data_t *data) nxt_php_unit_ctx = unit_ctx; - nxt_unit_run(unit_ctx); - - nxt_unit_done(unit_ctx); + nxt_unit_run(nxt_php_unit_ctx); + nxt_unit_done(nxt_php_unit_ctx); exit(0); @@ -512,6 +524,46 @@ nxt_php_set_target(nxt_task_t *task, nxt_php_target_t *target, } +static nxt_int_t +nxt_php_set_ini_path(nxt_task_t *task, nxt_str_t *ini_path, char *workdir) +{ + size_t wdlen; + u_char *p, *start; + + if (ini_path->start[0] == '/' || workdir == NULL) { + p = nxt_malloc(ini_path->length + 1); + if (nxt_slow_path(p == NULL)) { + return NXT_ERROR; + } + + start = p; + + } else { + wdlen = nxt_strlen(workdir); + + p = nxt_malloc(wdlen + ini_path->length + 2); + if (nxt_slow_path(p == NULL)) { + return NXT_ERROR; + } + + start = p; + + p = nxt_cpymem(p, workdir, wdlen); + + if (workdir[wdlen - 1] != '/') { + *p++ = '/'; + } + } + + p = nxt_cpymem(p, ini_path->start, ini_path->length); + *p = '\0'; + + nxt_php_sapi_module.php_ini_path_override = (char *) start; + + return NXT_OK; +} + + static void nxt_php_set_options(nxt_task_t *task, nxt_conf_value_t *options, int type) { diff --git a/test/test_php_isolation.py b/test/test_php_isolation.py index f4170f1b..556bd387 100644 --- a/test/test_php_isolation.py +++ b/test/test_php_isolation.py @@ -85,54 +85,3 @@ class TestPHPIsolation(TestApplicationPHP): assert 'json' in extensions, 'json in extensions list' assert 'unit' in extensions, 'unit in extensions list' - - def test_php_isolation_rootfs_no_language_libs(self, is_su): - isolation_features = self.available['features']['isolation'].keys() - - if not is_su: - if 'user' not in isolation_features: - pytest.skip('requires unprivileged userns or root') - - if not 'unprivileged_userns_clone' in isolation_features: - pytest.skip('requires unprivileged userns or root') - - if 'mnt' not in isolation_features: - pytest.skip('requires mnt ns') - - isolation = { - 'rootfs': option.test_dir, - 'automount': {'language_deps': False}, - 'namespaces': {'credential': not is_su, 'mount': not is_su}, - } - - self.load('list-extensions', isolation=isolation) - - assert 'success' in self.conf( - '"/php/list-extensions"', 'applications/list-extensions/root' - ) - - assert 'success' in self.conf( - {'file': '/php/list-extensions/php.ini'}, - 'applications/list-extensions/options', - ) - - assert 'success' in self.conf( - '"/php/list-extensions"', - 'applications/list-extensions/working_directory', - ) - - extensions = self.getjson()['body'] - - assert 'unit' in extensions, 'unit in extensions list' - assert 'json' not in extensions, 'json not in extensions list' - - assert 'success' in self.conf( - {'language_deps': True}, - 'applications/list-extensions/isolation/automount', - ) - - extensions = self.getjson()['body'] - - assert 'unit' in extensions, 'unit in extensions list 2' - assert 'json' in extensions, 'json in extensions list 2' - diff --git a/test/test_python_isolation.py b/test/test_python_isolation.py index 564ec79c..59ac670a 100644 --- a/test/test_python_isolation.py +++ b/test/test_python_isolation.py @@ -65,3 +65,33 @@ class TestPythonIsolation(TestApplicationPython): assert ( ret['body']['FileExists'] == True ), 'application exists in rootfs' + + def test_python_isolation_rootfs_no_language_deps(self, is_su): + isolation_features = self.available['features']['isolation'].keys() + + if 'mnt' not in isolation_features: + pytest.skip('requires mnt ns') + + if not is_su: + if 'user' not in isolation_features: + pytest.skip('requires unprivileged userns or root') + + if not 'unprivileged_userns_clone' in isolation_features: + pytest.skip('requires unprivileged userns or root') + + isolation = { + 'namespaces': {'credential': not is_su, 'mount': True}, + 'rootfs': self.temp_dir, + 'automount': {'language_deps': False} + } + + self.load('empty', isolation=isolation) + + assert (self.get()['status'] != 200), 'disabled language_deps' + + isolation['automount']['language_deps'] = True + + self.load('empty', isolation=isolation) + + assert (self.get()['status'] == 200), 'enabled language_deps' + |