From 5dc37cc306717998cf9f4bc8283a735d34c66cef Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Tue, 3 Sep 2019 14:23:13 +0300 Subject: [PATCH] Execute preload script under user defined by opcache.preload_user directive --- ext/opcache/ZendAccelerator.c | 77 +++++++++++++++++++++++++++ ext/opcache/ZendAccelerator.h | 3 ++ ext/opcache/zend_accelerator_module.c | 6 +++ 3 files changed, 86 insertions(+) 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 +# include # include +# include +# include #endif #include @@ -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 -- 2.40.0