Skip to content

Commit 0a9a8a9

Browse files
authored
Fix GH-9139: Allow FFI in opcache.preload when opcache.preload_user=root (#9473)
1 parent 1020b74 commit 0a9a8a9

File tree

3 files changed

+38
-37
lines changed

3 files changed

+38
-37
lines changed

ext/ffi/tests/300.phpt

-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ opcache
66
--SKIPIF--
77
<?php
88
if (substr(PHP_OS, 0, 3) == 'WIN') die('skip not for Windows');
9-
if (ini_get('opcache.preload_user')) die('skip FFI::load() does not support opcache.preload_user');
109
?>
1110
--INI--
1211
ffi.enable=1

ext/ffi/tests/bug78761.phpt

-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ ffi
55
--SKIPIF--
66
<?php
77
if (PHP_OS_FAMILY == 'Windows') die('skip Preloading is not supported on Windows');
8-
if (ini_get('opcache.preload_user')) die('skip FFI::load() does not support opcache.preload_user');
98
?>
109
--INI--
1110
opcache.enable_cli=1

ext/opcache/ZendAccelerator.c

+38-35
Original file line numberDiff line numberDiff line change
@@ -4609,14 +4609,15 @@ static int accel_finish_startup(void)
46094609
return SUCCESS;
46104610
}
46114611

4612-
if (geteuid() == 0) {
4612+
uid_t euid = geteuid();
4613+
if (euid == 0) {
46134614
pid_t pid;
46144615
struct passwd *pw;
46154616

46164617
if (!ZCG(accel_directives).preload_user
46174618
|| !*ZCG(accel_directives).preload_user) {
46184619
zend_shared_alloc_unlock();
4619-
zend_accel_error_noreturn(ACCEL_LOG_FATAL, "\"opcache.preload_user\" has not been defined");
4620+
zend_accel_error_noreturn(ACCEL_LOG_FATAL, "\"opcache.preload\" requires \"opcache.preload_user\" when running under uid 0");
46204621
return FAILURE;
46214622
}
46224623

@@ -4627,43 +4628,45 @@ static int accel_finish_startup(void)
46274628
return FAILURE;
46284629
}
46294630

4630-
pid = fork();
4631-
if (pid == -1) {
4632-
zend_shared_alloc_unlock();
4633-
zend_accel_error_noreturn(ACCEL_LOG_FATAL, "Preloading failed to fork()");
4634-
return FAILURE;
4635-
} else if (pid == 0) { /* children */
4636-
if (setgid(pw->pw_gid) < 0) {
4637-
zend_accel_error(ACCEL_LOG_WARNING, "Preloading failed to setgid(%d)", pw->pw_gid);
4638-
exit(1);
4639-
}
4640-
if (initgroups(pw->pw_name, pw->pw_gid) < 0) {
4641-
zend_accel_error(ACCEL_LOG_WARNING, "Preloading failed to initgroups(\"%s\", %d)", pw->pw_name, pw->pw_uid);
4642-
exit(1);
4643-
}
4644-
if (setuid(pw->pw_uid) < 0) {
4645-
zend_accel_error(ACCEL_LOG_WARNING, "Preloading failed to setuid(%d)", pw->pw_uid);
4646-
exit(1);
4647-
}
4648-
in_child = true;
4649-
} else { /* parent */
4650-
int status;
4651-
4652-
if (waitpid(pid, &status, 0) < 0) {
4631+
if (pw->pw_uid != euid) {
4632+
pid = fork();
4633+
if (pid == -1) {
46534634
zend_shared_alloc_unlock();
4654-
zend_accel_error_noreturn(ACCEL_LOG_FATAL, "Preloading failed to waitpid(%d)", pid);
4635+
zend_accel_error_noreturn(ACCEL_LOG_FATAL, "Preloading failed to fork()");
46554636
return FAILURE;
4656-
}
4637+
} else if (pid == 0) { /* children */
4638+
if (setgid(pw->pw_gid) < 0) {
4639+
zend_accel_error(ACCEL_LOG_WARNING, "Preloading failed to setgid(%d)", pw->pw_gid);
4640+
exit(1);
4641+
}
4642+
if (initgroups(pw->pw_name, pw->pw_gid) < 0) {
4643+
zend_accel_error(ACCEL_LOG_WARNING, "Preloading failed to initgroups(\"%s\", %d)", pw->pw_name, pw->pw_uid);
4644+
exit(1);
4645+
}
4646+
if (setuid(pw->pw_uid) < 0) {
4647+
zend_accel_error(ACCEL_LOG_WARNING, "Preloading failed to setuid(%d)", pw->pw_uid);
4648+
exit(1);
4649+
}
4650+
in_child = true;
4651+
} else { /* parent */
4652+
int status;
46574653

4658-
if (ZCSG(preload_script)) {
4659-
preload_load();
4660-
}
4654+
if (waitpid(pid, &status, 0) < 0) {
4655+
zend_shared_alloc_unlock();
4656+
zend_accel_error_noreturn(ACCEL_LOG_FATAL, "Preloading failed to waitpid(%d)", pid);
4657+
return FAILURE;
4658+
}
46614659

4662-
zend_shared_alloc_unlock();
4663-
if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
4664-
return SUCCESS;
4665-
} else {
4666-
return FAILURE;
4660+
if (ZCSG(preload_script)) {
4661+
preload_load();
4662+
}
4663+
4664+
zend_shared_alloc_unlock();
4665+
if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
4666+
return SUCCESS;
4667+
} else {
4668+
return FAILURE;
4669+
}
46674670
}
46684671
}
46694672
} else {

0 commit comments

Comments
 (0)