Skip to content

Commit 3be8323

Browse files
committed
Merge branch 'PHP-7.4'
* PHP-7.4: Execute preload script under user defined by opcache.preload_user directive
2 parents 37713c8 + 5dc37cc commit 3be8323

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
@@ -77,7 +77,10 @@ typedef int gid_t;
7777

7878
#ifndef ZEND_WIN32
7979
# include <sys/types.h>
80+
# include <sys/wait.h>
8081
# include <sys/ipc.h>
82+
# include <pwd.h>
83+
# include <grp.h>
8184
#endif
8285

8386
#include <sys/stat.h>
@@ -4532,6 +4535,9 @@ static int accel_finish_startup(void)
45324535
}
45334536

45344537
if (ZCG(accel_directives).preload && *ZCG(accel_directives).preload) {
4538+
#ifndef ZEND_WIN32
4539+
int in_child = 0;
4540+
#endif
45354541
int ret = SUCCESS;
45364542
int rc;
45374543
int orig_error_reporting;
@@ -4564,6 +4570,67 @@ static int accel_finish_startup(void)
45644570
return SUCCESS;
45654571
}
45664572

4573+
#ifndef ZEND_WIN32
4574+
if (geteuid() == 0) {
4575+
pid_t pid;
4576+
struct passwd *pw;
4577+
4578+
if (!ZCG(accel_directives).preload_user
4579+
|| !*ZCG(accel_directives).preload_user) {
4580+
zend_shared_alloc_unlock();
4581+
zend_accel_error(ACCEL_LOG_FATAL, "\"opcache.preload_user\" has not been defined");
4582+
return FAILURE;
4583+
}
4584+
4585+
pw = getpwnam(ZCG(accel_directives).preload_user);
4586+
if (pw == NULL) {
4587+
zend_shared_alloc_unlock();
4588+
zend_accel_error(ACCEL_LOG_FATAL, "Preloading failed to getpwnam(\"%s\")", ZCG(accel_directives).preload_user);
4589+
return FAILURE;
4590+
}
4591+
4592+
pid = fork();
4593+
if (pid == -1) {
4594+
zend_shared_alloc_unlock();
4595+
zend_accel_error(ACCEL_LOG_FATAL, "Preloading failed to fork()");
4596+
return FAILURE;
4597+
} else if (pid == 0) { /* children */
4598+
if (setgid(pw->pw_gid) < 0) {
4599+
zend_accel_error(ACCEL_LOG_WARNING, "Preloading failed to setgid(%d)", pw->pw_gid);
4600+
exit(1);
4601+
}
4602+
if (initgroups(pw->pw_name, pw->pw_gid) < 0) {
4603+
zend_accel_error(ACCEL_LOG_WARNING, "Preloading failed to initgroups(\"%s\", %d)", pw->pw_name, pw->pw_uid);
4604+
exit(1);
4605+
}
4606+
if (setuid(pw->pw_uid) < 0) {
4607+
zend_accel_error(ACCEL_LOG_WARNING, "Preloading failed to setuid(%d)", pw->pw_uid);
4608+
exit(1);
4609+
}
4610+
in_child = 1;
4611+
} else { /* parent */
4612+
int status;
4613+
4614+
if (waitpid(pid, &status, 0) < 0) {
4615+
zend_shared_alloc_unlock();
4616+
zend_accel_error(ACCEL_LOG_FATAL, "Preloading failed to waitpid(%d)", pid);
4617+
return FAILURE;
4618+
}
4619+
zend_shared_alloc_unlock();
4620+
if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
4621+
return SUCCESS;
4622+
} else {
4623+
return FAILURE;
4624+
}
4625+
}
4626+
} else {
4627+
if (ZCG(accel_directives).preload_user
4628+
&& *ZCG(accel_directives).preload_user) {
4629+
zend_accel_error(ACCEL_LOG_WARNING, "\"opcache.preload_user\" is ignored");
4630+
}
4631+
}
4632+
#endif
4633+
45674634
sapi_module.activate = NULL;
45684635
sapi_module.deactivate = NULL;
45694636
sapi_module.register_server_variables = NULL;
@@ -4639,6 +4706,16 @@ static int accel_finish_startup(void)
46394706

46404707
sapi_activate();
46414708

4709+
#ifndef ZEND_WIN32
4710+
if (in_child) {
4711+
if (ret == SUCCESS) {
4712+
exit(0);
4713+
} else {
4714+
exit(2);
4715+
}
4716+
}
4717+
#endif
4718+
46424719
return ret;
46434720
}
46444721

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
@@ -306,6 +306,9 @@ ZEND_INI_BEGIN()
306306
STD_PHP_INI_BOOLEAN("opcache.huge_code_pages" , "0" , PHP_INI_SYSTEM, OnUpdateBool, accel_directives.huge_code_pages, zend_accel_globals, accel_globals)
307307
#endif
308308
STD_PHP_INI_ENTRY("opcache.preload" , "" , PHP_INI_SYSTEM, OnUpdateStringUnempty, accel_directives.preload, zend_accel_globals, accel_globals)
309+
#ifndef ZEND_WIN32
310+
STD_PHP_INI_ENTRY("opcache.preload_user" , "" , PHP_INI_SYSTEM, OnUpdateStringUnempty, accel_directives.preload_user, zend_accel_globals, accel_globals)
311+
#endif
309312
#if ZEND_WIN32
310313
STD_PHP_INI_ENTRY("opcache.cache_id" , "" , PHP_INI_SYSTEM, OnUpdateString, accel_directives.cache_id, zend_accel_globals, accel_globals)
311314
#endif
@@ -774,6 +777,9 @@ static ZEND_FUNCTION(opcache_get_configuration)
774777
add_assoc_bool(&directives, "opcache.huge_code_pages", ZCG(accel_directives).huge_code_pages);
775778
#endif
776779
add_assoc_string(&directives, "opcache.preload", STRING_NOT_NULL(ZCG(accel_directives).preload));
780+
#ifndef ZEND_WIN32
781+
add_assoc_string(&directives, "opcache.preload_user", STRING_NOT_NULL(ZCG(accel_directives).preload_user));
782+
#endif
777783
#if ZEND_WIN32
778784
add_assoc_string(&directives, "opcache.cache_id", STRING_NOT_NULL(ZCG(accel_directives).cache_id));
779785
#endif

0 commit comments

Comments
 (0)