Skip to content

Commit 5dc37cc

Browse files
committed
Execute preload script under user defined by opcache.preload_user directive
1 parent 518c651 commit 5dc37cc

File tree

3 files changed

+86
-0
lines changed

3 files changed

+86
-0
lines changed

ext/opcache/ZendAccelerator.c

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,10 @@ typedef int gid_t;
7373

7474
#ifndef ZEND_WIN32
7575
# include <sys/types.h>
76+
# include <sys/wait.h>
7677
# include <sys/ipc.h>
78+
# include <pwd.h>
79+
# include <grp.h>
7780
#endif
7881

7982
#include <sys/stat.h>
@@ -4478,6 +4481,9 @@ static int accel_finish_startup(void)
44784481
}
44794482

44804483
if (ZCG(accel_directives).preload && *ZCG(accel_directives).preload) {
4484+
#ifndef ZEND_WIN32
4485+
int in_child = 0;
4486+
#endif
44814487
int ret = SUCCESS;
44824488
int rc;
44834489
int orig_error_reporting;
@@ -4510,6 +4516,67 @@ static int accel_finish_startup(void)
45104516
return SUCCESS;
45114517
}
45124518

4519+
#ifndef ZEND_WIN32
4520+
if (geteuid() == 0) {
4521+
pid_t pid;
4522+
struct passwd *pw;
4523+
4524+
if (!ZCG(accel_directives).preload_user
4525+
|| !*ZCG(accel_directives).preload_user) {
4526+
zend_shared_alloc_unlock();
4527+
zend_accel_error(ACCEL_LOG_FATAL, "\"opcache.preload_user\" has not been defined");
4528+
return FAILURE;
4529+
}
4530+
4531+
pw = getpwnam(ZCG(accel_directives).preload_user);
4532+
if (pw == NULL) {
4533+
zend_shared_alloc_unlock();
4534+
zend_accel_error(ACCEL_LOG_FATAL, "Preloading failed to getpwnam(\"%s\")", ZCG(accel_directives).preload_user);
4535+
return FAILURE;
4536+
}
4537+
4538+
pid = fork();
4539+
if (pid == -1) {
4540+
zend_shared_alloc_unlock();
4541+
zend_accel_error(ACCEL_LOG_FATAL, "Preloading failed to fork()");
4542+
return FAILURE;
4543+
} else if (pid == 0) { /* children */
4544+
if (setgid(pw->pw_gid) < 0) {
4545+
zend_accel_error(ACCEL_LOG_WARNING, "Preloading failed to setgid(%d)", pw->pw_gid);
4546+
exit(1);
4547+
}
4548+
if (initgroups(pw->pw_name, pw->pw_gid) < 0) {
4549+
zend_accel_error(ACCEL_LOG_WARNING, "Preloading failed to initgroups(\"%s\", %d)", pw->pw_name, pw->pw_uid);
4550+
exit(1);
4551+
}
4552+
if (setuid(pw->pw_uid) < 0) {
4553+
zend_accel_error(ACCEL_LOG_WARNING, "Preloading failed to setuid(%d)", pw->pw_uid);
4554+
exit(1);
4555+
}
4556+
in_child = 1;
4557+
} else { /* parent */
4558+
int status;
4559+
4560+
if (waitpid(pid, &status, 0) < 0) {
4561+
zend_shared_alloc_unlock();
4562+
zend_accel_error(ACCEL_LOG_FATAL, "Preloading failed to waitpid(%d)", pid);
4563+
return FAILURE;
4564+
}
4565+
zend_shared_alloc_unlock();
4566+
if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
4567+
return SUCCESS;
4568+
} else {
4569+
return FAILURE;
4570+
}
4571+
}
4572+
} else {
4573+
if (ZCG(accel_directives).preload_user
4574+
&& *ZCG(accel_directives).preload_user) {
4575+
zend_accel_error(ACCEL_LOG_WARNING, "\"opcache.preload_user\" is ignored");
4576+
}
4577+
}
4578+
#endif
4579+
45134580
sapi_module.activate = NULL;
45144581
sapi_module.deactivate = NULL;
45154582
sapi_module.register_server_variables = NULL;
@@ -4585,6 +4652,16 @@ static int accel_finish_startup(void)
45854652

45864653
sapi_activate();
45874654

4655+
#ifndef ZEND_WIN32
4656+
if (in_child) {
4657+
if (ret == SUCCESS) {
4658+
exit(0);
4659+
} else {
4660+
exit(2);
4661+
}
4662+
}
4663+
#endif
4664+
45884665
return ret;
45894666
}
45904667

ext/opcache/ZendAccelerator.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,9 @@ typedef struct _zend_accel_directives {
185185
zend_bool huge_code_pages;
186186
#endif
187187
char *preload;
188+
#ifndef ZEND_WIN32
189+
char *preload_user;
190+
#endif
188191
#ifdef ZEND_WIN32
189192
char *cache_id;
190193
#endif

ext/opcache/zend_accelerator_module.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -321,6 +321,9 @@ ZEND_INI_BEGIN()
321321
STD_PHP_INI_BOOLEAN("opcache.huge_code_pages" , "0" , PHP_INI_SYSTEM, OnUpdateBool, accel_directives.huge_code_pages, zend_accel_globals, accel_globals)
322322
#endif
323323
STD_PHP_INI_ENTRY("opcache.preload" , "" , PHP_INI_SYSTEM, OnUpdateStringUnempty, accel_directives.preload, zend_accel_globals, accel_globals)
324+
#ifndef ZEND_WIN32
325+
STD_PHP_INI_ENTRY("opcache.preload_user" , "" , PHP_INI_SYSTEM, OnUpdateStringUnempty, accel_directives.preload_user, zend_accel_globals, accel_globals)
326+
#endif
324327
#if ZEND_WIN32
325328
STD_PHP_INI_ENTRY("opcache.cache_id" , "" , PHP_INI_SYSTEM, OnUpdateString, accel_directives.cache_id, zend_accel_globals, accel_globals)
326329
#endif
@@ -771,6 +774,9 @@ static ZEND_FUNCTION(opcache_get_configuration)
771774
add_assoc_bool(&directives, "opcache.huge_code_pages", ZCG(accel_directives).huge_code_pages);
772775
#endif
773776
add_assoc_string(&directives, "opcache.preload", STRING_NOT_NULL(ZCG(accel_directives).preload));
777+
#ifndef ZEND_WIN32
778+
add_assoc_string(&directives, "opcache.preload_user", STRING_NOT_NULL(ZCG(accel_directives).preload_user));
779+
#endif
774780
#if ZEND_WIN32
775781
add_assoc_string(&directives, "opcache.cache_id", STRING_NOT_NULL(ZCG(accel_directives).cache_id));
776782
#endif

0 commit comments

Comments
 (0)