summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry Stogov <dmitry@zend.com>2019-09-03 14:23:13 +0300
committerDmitry Stogov <dmitry@zend.com>2019-09-03 14:23:13 +0300
commit5dc37cc306717998cf9f4bc8283a735d34c66cef (patch)
tree313723c82f33a507f9accc8a7f3ce95f8056ab84
parent518c651c663a2f09fb05ecea407ea0ab64f9bb51 (diff)
downloadphp-git-5dc37cc306717998cf9f4bc8283a735d34c66cef.tar.gz
Execute preload script under user defined by opcache.preload_user directive
-rw-r--r--ext/opcache/ZendAccelerator.c77
-rw-r--r--ext/opcache/ZendAccelerator.h3
-rw-r--r--ext/opcache/zend_accelerator_module.c6
3 files changed, 86 insertions, 0 deletions
diff --git a/ext/opcache/ZendAccelerator.c b/ext/opcache/ZendAccelerator.c
index 6dcf4e43de..311676a265 100644
--- a/ext/opcache/ZendAccelerator.c
+++ b/ext/opcache/ZendAccelerator.c
@@ -73,7 +73,10 @@ typedef int gid_t;
#ifndef ZEND_WIN32
# include <sys/types.h>
+# include <sys/wait.h>
# include <sys/ipc.h>
+# include <pwd.h>
+# include <grp.h>
#endif
#include <sys/stat.h>
@@ -4478,6 +4481,9 @@ static int accel_finish_startup(void)
}
if (ZCG(accel_directives).preload && *ZCG(accel_directives).preload) {
+#ifndef ZEND_WIN32
+ int in_child = 0;
+#endif
int ret = SUCCESS;
int rc;
int orig_error_reporting;
@@ -4510,6 +4516,67 @@ static int accel_finish_startup(void)
return SUCCESS;
}
+#ifndef ZEND_WIN32
+ if (geteuid() == 0) {
+ pid_t pid;
+ struct passwd *pw;
+
+ if (!ZCG(accel_directives).preload_user
+ || !*ZCG(accel_directives).preload_user) {
+ zend_shared_alloc_unlock();
+ zend_accel_error(ACCEL_LOG_FATAL, "\"opcache.preload_user\" has not been defined");
+ return FAILURE;
+ }
+
+ pw = getpwnam(ZCG(accel_directives).preload_user);
+ if (pw == NULL) {
+ zend_shared_alloc_unlock();
+ zend_accel_error(ACCEL_LOG_FATAL, "Preloading failed to getpwnam(\"%s\")", ZCG(accel_directives).preload_user);
+ return FAILURE;
+ }
+
+ pid = fork();
+ if (pid == -1) {
+ zend_shared_alloc_unlock();
+ zend_accel_error(ACCEL_LOG_FATAL, "Preloading failed to fork()");
+ return FAILURE;
+ } else if (pid == 0) { /* children */
+ if (setgid(pw->pw_gid) < 0) {
+ zend_accel_error(ACCEL_LOG_WARNING, "Preloading failed to setgid(%d)", pw->pw_gid);
+ exit(1);
+ }
+ if (initgroups(pw->pw_name, pw->pw_gid) < 0) {
+ zend_accel_error(ACCEL_LOG_WARNING, "Preloading failed to initgroups(\"%s\", %d)", pw->pw_name, pw->pw_uid);
+ exit(1);
+ }
+ if (setuid(pw->pw_uid) < 0) {
+ zend_accel_error(ACCEL_LOG_WARNING, "Preloading failed to setuid(%d)", pw->pw_uid);
+ exit(1);
+ }
+ in_child = 1;
+ } else { /* parent */
+ int status;
+
+ if (waitpid(pid, &status, 0) < 0) {
+ zend_shared_alloc_unlock();
+ zend_accel_error(ACCEL_LOG_FATAL, "Preloading failed to waitpid(%d)", pid);
+ return FAILURE;
+ }
+ zend_shared_alloc_unlock();
+ if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
+ return SUCCESS;
+ } else {
+ return FAILURE;
+ }
+ }
+ } else {
+ if (ZCG(accel_directives).preload_user
+ && *ZCG(accel_directives).preload_user) {
+ zend_accel_error(ACCEL_LOG_WARNING, "\"opcache.preload_user\" is ignored");
+ }
+ }
+#endif
+
sapi_module.activate = NULL;
sapi_module.deactivate = NULL;
sapi_module.register_server_variables = NULL;
@@ -4585,6 +4652,16 @@ static int accel_finish_startup(void)
sapi_activate();
+#ifndef ZEND_WIN32
+ if (in_child) {
+ if (ret == SUCCESS) {
+ exit(0);
+ } else {
+ exit(2);
+ }
+ }
+#endif
+
return ret;
}
diff --git a/ext/opcache/ZendAccelerator.h b/ext/opcache/ZendAccelerator.h
index 20ac84583d..c2f95d7c41 100644
--- a/ext/opcache/ZendAccelerator.h
+++ b/ext/opcache/ZendAccelerator.h
@@ -185,6 +185,9 @@ typedef struct _zend_accel_directives {
zend_bool huge_code_pages;
#endif
char *preload;
+#ifndef ZEND_WIN32
+ char *preload_user;
+#endif
#ifdef ZEND_WIN32
char *cache_id;
#endif
diff --git a/ext/opcache/zend_accelerator_module.c b/ext/opcache/zend_accelerator_module.c
index 25f3cc5b81..eb5b1c7537 100644
--- a/ext/opcache/zend_accelerator_module.c
+++ b/ext/opcache/zend_accelerator_module.c
@@ -321,6 +321,9 @@ ZEND_INI_BEGIN()
STD_PHP_INI_BOOLEAN("opcache.huge_code_pages" , "0" , PHP_INI_SYSTEM, OnUpdateBool, accel_directives.huge_code_pages, zend_accel_globals, accel_globals)
#endif
STD_PHP_INI_ENTRY("opcache.preload" , "" , PHP_INI_SYSTEM, OnUpdateStringUnempty, accel_directives.preload, zend_accel_globals, accel_globals)
+#ifndef ZEND_WIN32
+ STD_PHP_INI_ENTRY("opcache.preload_user" , "" , PHP_INI_SYSTEM, OnUpdateStringUnempty, accel_directives.preload_user, zend_accel_globals, accel_globals)
+#endif
#if ZEND_WIN32
STD_PHP_INI_ENTRY("opcache.cache_id" , "" , PHP_INI_SYSTEM, OnUpdateString, accel_directives.cache_id, zend_accel_globals, accel_globals)
#endif
@@ -771,6 +774,9 @@ static ZEND_FUNCTION(opcache_get_configuration)
add_assoc_bool(&directives, "opcache.huge_code_pages", ZCG(accel_directives).huge_code_pages);
#endif
add_assoc_string(&directives, "opcache.preload", STRING_NOT_NULL(ZCG(accel_directives).preload));
+#ifndef ZEND_WIN32
+ add_assoc_string(&directives, "opcache.preload_user", STRING_NOT_NULL(ZCG(accel_directives).preload_user));
+#endif
#if ZEND_WIN32
add_assoc_string(&directives, "opcache.cache_id", STRING_NOT_NULL(ZCG(accel_directives).cache_id));
#endif