Skip to content

Commit

Permalink
Fix GH-9139: Allow FFI in opcache.preload when opcache.preload_user=…
Browse files Browse the repository at this point in the history
…root (#9473)
  • Loading branch information
arnaud-lb authored Sep 9, 2022
1 parent 1020b74 commit 0a9a8a9
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 37 deletions.
1 change: 0 additions & 1 deletion ext/ffi/tests/300.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ opcache
--SKIPIF--
<?php
if (substr(PHP_OS, 0, 3) == 'WIN') die('skip not for Windows');
if (ini_get('opcache.preload_user')) die('skip FFI::load() does not support opcache.preload_user');
?>
--INI--
ffi.enable=1
Expand Down
1 change: 0 additions & 1 deletion ext/ffi/tests/bug78761.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ ffi
--SKIPIF--
<?php
if (PHP_OS_FAMILY == 'Windows') die('skip Preloading is not supported on Windows');
if (ini_get('opcache.preload_user')) die('skip FFI::load() does not support opcache.preload_user');
?>
--INI--
opcache.enable_cli=1
Expand Down
73 changes: 38 additions & 35 deletions ext/opcache/ZendAccelerator.c
Original file line number Diff line number Diff line change
Expand Up @@ -4609,14 +4609,15 @@ static int accel_finish_startup(void)
return SUCCESS;
}

if (geteuid() == 0) {
uid_t euid = geteuid();
if (euid == 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_noreturn(ACCEL_LOG_FATAL, "\"opcache.preload_user\" has not been defined");
zend_accel_error_noreturn(ACCEL_LOG_FATAL, "\"opcache.preload\" requires \"opcache.preload_user\" when running under uid 0");
return FAILURE;
}

Expand All @@ -4627,43 +4628,45 @@ static int accel_finish_startup(void)
return FAILURE;
}

pid = fork();
if (pid == -1) {
zend_shared_alloc_unlock();
zend_accel_error_noreturn(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 = true;
} else { /* parent */
int status;

if (waitpid(pid, &status, 0) < 0) {
if (pw->pw_uid != euid) {
pid = fork();
if (pid == -1) {
zend_shared_alloc_unlock();
zend_accel_error_noreturn(ACCEL_LOG_FATAL, "Preloading failed to waitpid(%d)", pid);
zend_accel_error_noreturn(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 = true;
} else { /* parent */
int status;

if (ZCSG(preload_script)) {
preload_load();
}
if (waitpid(pid, &status, 0) < 0) {
zend_shared_alloc_unlock();
zend_accel_error_noreturn(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;
if (ZCSG(preload_script)) {
preload_load();
}

zend_shared_alloc_unlock();
if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
return SUCCESS;
} else {
return FAILURE;
}
}
}
} else {
Expand Down

0 comments on commit 0a9a8a9

Please sign in to comment.