Skip to content

Commit a605261

Browse files
committed
Do not require opcache.preload_user in cli SAPIs
1 parent 01cc975 commit a605261

8 files changed

+259
-3
lines changed

ext/opcache/ZendAccelerator.c

+7
Original file line numberDiff line numberDiff line change
@@ -4679,6 +4679,13 @@ static int accel_finish_startup_preload_subprocess(pid_t *pid)
46794679
if (!ZCG(accel_directives).preload_user
46804680
|| !*ZCG(accel_directives).preload_user) {
46814681

4682+
bool sapi_requires_preload_user = !(strcmp(sapi_module.name, "cli") == 0
4683+
|| strcmp(sapi_module.name, "phpdbg") == 0);
4684+
4685+
if (!sapi_requires_preload_user) {
4686+
*pid = -1;
4687+
return SUCCESS;
4688+
}
46824689

46834690
zend_shared_alloc_unlock();
46844691
zend_accel_error_noreturn(ACCEL_LOG_FATAL, "\"opcache.preload\" requires \"opcache.preload_user\" when running under uid 0");

ext/opcache/tests/preload_user.inc

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<?php
2+
3+
var_dump(posix_getuid() === 0);
4+
5+
require __DIR__ . '/preload.inc';
+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
--TEST--
2+
preload_user has no effect when euid is not 0
3+
--INI--
4+
opcache.enable=1
5+
opcache.enable_cli=1
6+
opcache.optimization_level=-1
7+
opcache.preload={PWD}/preload.inc
8+
opcache.preload_user=php
9+
opcache.log_verbosity_level=2
10+
--EXTENSIONS--
11+
opcache
12+
posix
13+
--SKIPIF--
14+
<?php
15+
if (PHP_OS_FAMILY == 'Windows') die('skip Preloading is not supported on Windows');
16+
if (posix_geteuid() === 0) die('skip Test needs non-root user');
17+
?>
18+
--FILE--
19+
<?php
20+
var_dump(function_exists("f1"));
21+
var_dump(function_exists("f2"));
22+
?>
23+
OK
24+
--EXPECTF--
25+
%sWarning "opcache.preload_user" is ignored
26+
bool(true)
27+
bool(false)
28+
OK
+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
--TEST--
2+
preload_user sets the process uid
3+
--INI--
4+
opcache.enable=1
5+
opcache.enable_cli=1
6+
opcache.optimization_level=-1
7+
opcache.preload={PWD}/preload_user.inc
8+
opcache.preload_user={ENV:TEST_NON_ROOT_USER}
9+
opcache.log_verbosity_level=2
10+
--EXTENSIONS--
11+
opcache
12+
posix
13+
--SKIPIF--
14+
<?php
15+
if (PHP_OS_FAMILY == 'Windows') die('skip Preloading is not supported on Windows');
16+
if (posix_geteuid() !== 0) die('skip Test needs root user');
17+
?>
18+
--FILE--
19+
<?php
20+
var_dump(function_exists("f1"));
21+
var_dump(function_exists("f2"));
22+
?>
23+
OK
24+
--EXPECTF--
25+
bool(false)
26+
bool(true)
27+
bool(false)
28+
OK
+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
--TEST--
2+
preload_user has no effect when preload_user is the current user
3+
--INI--
4+
opcache.enable=1
5+
opcache.enable_cli=1
6+
opcache.optimization_level=-1
7+
opcache.preload={PWD}/preload_user.inc
8+
opcache.preload_user=root
9+
opcache.log_verbosity_level=2
10+
--EXTENSIONS--
11+
opcache
12+
posix
13+
--SKIPIF--
14+
<?php
15+
if (PHP_OS_FAMILY == 'Windows') die('skip Preloading is not supported on Windows');
16+
if (posix_geteuid() !== 0) die('skip Test needs root user');
17+
if (posix_getpwnam('root') === false) die('skip Root user does not exist');
18+
?>
19+
--FILE--
20+
<?php
21+
var_dump(function_exists("f1"));
22+
var_dump(function_exists("f2"));
23+
?>
24+
OK
25+
--EXPECTF--
26+
bool(true)
27+
bool(true)
28+
bool(false)
29+
OK
+72
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
--TEST--
2+
preload_user is required when euid is 0 under non-cli SAPIs
3+
--INI--
4+
--EXTENSIONS--
5+
opcache
6+
posix
7+
--SKIPIF--
8+
<?php
9+
require dirname(__DIR__, 3) . '/sapi/fpm/tests/skipif.inc';
10+
if (PHP_OS_FAMILY == 'Windows') die('skip Preloading is not supported on Windows');
11+
if (posix_geteuid() !== 0) die('skip Test needs root user');
12+
?>
13+
--FILE--
14+
<?php
15+
16+
require_once dirname(__DIR__, 3) . '/sapi/fpm/tests/tester.inc';
17+
18+
$cfg = <<<EOT
19+
[global]
20+
error_log = {{FILE:LOG}}
21+
[unconfined]
22+
listen = {{ADDR}}
23+
pm = dynamic
24+
pm.max_children = 5
25+
pm.start_servers = 2
26+
pm.min_spare_servers = 1
27+
pm.max_spare_servers = 3
28+
EOT;
29+
30+
$code = <<<EOT
31+
<?php
32+
var_dump(function_exists("f1"));
33+
var_dump(function_exists("f2"));
34+
?>
35+
OK
36+
EOT;
37+
38+
$args = [];
39+
if (file_exists(ini_get('extension_dir').'/opcache.so')) {
40+
$args[] = '-dzend_extension='.ini_get('extension_dir').'/opcache.so';
41+
}
42+
if (file_exists(ini_get('extension_dir').'/posix.so')) {
43+
$args[] = '-dextension='.ini_get('extension_dir').'/posix.so';
44+
}
45+
$args = [
46+
...$args,
47+
'-dopcache.enable=1',
48+
'-dopcache.optimization_level=-1',
49+
'-dopcache.preload='.__DIR__.'/preload.inc',
50+
'-dopcache.log_verbosity_level=2',
51+
];
52+
53+
$tester = new FPM\Tester($cfg, $code);
54+
$tester->start($args);
55+
var_dump($tester->getLogLines(1));
56+
$tester->terminate();
57+
$tester->close();
58+
59+
?>
60+
Done
61+
--EXPECTF--
62+
array(1) {
63+
[0]=>
64+
string(%d) "%sFatal Error "opcache.preload" requires "opcache.preload_user" when running under uid 0
65+
"
66+
}
67+
Done
68+
--CLEAN--
69+
<?php
70+
require_once dirname(__DIR__, 3) . '/sapi/fpm/tests/tester.inc';
71+
FPM\Tester::clean();
72+
?>
+77
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
--TEST--
2+
preload_user=root is allowed under non-cli SAPIs
3+
--INI--
4+
--EXTENSIONS--
5+
opcache
6+
posix
7+
--SKIPIF--
8+
<?php
9+
require dirname(__DIR__, 3) . '/sapi/fpm/tests/skipif.inc';
10+
if (PHP_OS_FAMILY == 'Windows') die('skip Preloading is not supported on Windows');
11+
if (posix_geteuid() !== 0) die('skip Test needs root user');
12+
if (posix_getpwnam('root') === false) die('skip Root user does not exist');
13+
?>
14+
--FILE--
15+
<?php
16+
17+
require_once dirname(__DIR__, 3) . '/sapi/fpm/tests/tester.inc';
18+
19+
$cfg = <<<EOT
20+
[global]
21+
error_log = {{FILE:LOG}}
22+
[unconfined]
23+
listen = {{ADDR}}
24+
pm = dynamic
25+
pm.max_children = 5
26+
pm.start_servers = 2
27+
pm.min_spare_servers = 1
28+
pm.max_spare_servers = 3
29+
EOT;
30+
31+
$code = <<<EOT
32+
<?php
33+
var_dump(function_exists("f1"));
34+
var_dump(function_exists("f2"));
35+
?>
36+
OK
37+
EOT;
38+
39+
$args = [];
40+
if (file_exists(ini_get('extension_dir').'/opcache.so')) {
41+
$args[] = '-dzend_extension='.ini_get('extension_dir').'/opcache.so';
42+
}
43+
if (file_exists(ini_get('extension_dir').'/posix.so')) {
44+
$args[] = '-dextension='.ini_get('extension_dir').'/posix.so';
45+
}
46+
$args = [
47+
...$args,
48+
'-dopcache.enable=1',
49+
'-dopcache.optimization_level=-1',
50+
'-dopcache.preload='.__DIR__.'/preload.inc',
51+
'-dopcache.preload_user=root',
52+
'-dopcache.log_verbosity_level=2',
53+
'-R',
54+
];
55+
56+
$tester = new FPM\Tester($cfg, $code);
57+
$tester->start($args);
58+
$tester->expectLogStartNotices();
59+
$tester
60+
->request()
61+
->expectBody([
62+
'bool(true)',
63+
'bool(false)',
64+
'OK',
65+
]);
66+
$tester->terminate();
67+
$tester->close();
68+
69+
?>
70+
Done
71+
--EXPECT--
72+
Done
73+
--CLEAN--
74+
<?php
75+
require_once dirname(__DIR__, 3) . '/sapi/fpm/tests/tester.inc';
76+
FPM\Tester::clean();
77+
?>

run-tests.php

+13-3
Original file line numberDiff line numberDiff line change
@@ -2067,9 +2067,6 @@ function run_test(string $php, $file, array $env): string
20672067
// Make sure warnings still show up on the second run.
20682068
$ini_settings['opcache.record_warnings'] = '1';
20692069
}
2070-
if (extension_loaded('posix') && posix_getuid() === 0) {
2071-
$ini_settings['opcache.preload_user'] = 'root';
2072-
}
20732070

20742071
// Any special ini settings
20752072
// these may overwrite the test defaults...
@@ -2078,6 +2075,19 @@ function run_test(string $php, $file, array $env): string
20782075
$ini = str_replace('{TMP}', sys_get_temp_dir(), $ini);
20792076
$replacement = IS_WINDOWS ? '"' . PHP_BINARY . ' -r \"while ($in = fgets(STDIN)) echo $in;\" > $1"' : 'tee $1 >/dev/null';
20802077
$ini = preg_replace('/{MAIL:(\S+)}/', $replacement, $ini);
2078+
$skip = false;
2079+
$ini = preg_replace_callback('/{ENV:(\S+)}/', function ($m) use (&$skip) {
2080+
$name = $m[1];
2081+
$value = getenv($name);
2082+
if ($value === false) {
2083+
$skip = sprintf('Environment variable %s is not set', $name);
2084+
return '';
2085+
}
2086+
return $value;
2087+
}, $ini);
2088+
if ($skip !== false) {
2089+
return skip_test($tested, $tested_file, $shortname, $skip);
2090+
}
20812091
settings2array(preg_split("/[\n\r]+/", $ini), $ini_settings);
20822092

20832093
if ($num_repeats > 1 && isset($ini_settings['opcache.opt_debug_level'])) {

0 commit comments

Comments
 (0)