Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 77 additions & 0 deletions ext/opcache/ZendAccelerator.c
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}

Expand Down
3 changes: 3 additions & 0 deletions ext/opcache/ZendAccelerator.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
6 changes: 6 additions & 0 deletions ext/opcache/zend_accelerator_module.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If there is no Windows support, I think the ini directive should be #ifndef ZEND_WIN32 only.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume, Windows is not affected, but I'm not completely sure.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm with @cmb69 here - it should be in an #ifndef ZEND_WIN32 block (and the char *preload_user; too, of course).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As I understand it, there is not need for preload.user on Windows, but @weltling may know better. :)

#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
Expand Down Expand Up @@ -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
Expand Down