mirror of
https://github.com/php/php-src.git
synced 2024-09-22 02:17:32 +00:00
Add possibility to lower timer resolution
The recently discovered security flaw Spectre requires a high resolution timer. To the today's knowledge, PHP can't be used to create an attack for this flaw. Still some concerns were raised, that there might be impact in shared hosting environments. This patch adds a possibility to reduce the timer resolution by an ini setting, thus giving administrators full control. Especially, as the flaw was also demonstrated by an abuse of the JS engine in a browser, Firefox reduced several time sources to 20us. Any programming language, that doesn't compile to JIT, won't be able to produce an attack vector for Meltdown and Spectre, at least by todays knowledge. There are also other factors that say that the security concern on the hrtime feature is to the big part not justified, still we aim JIT in the future. Thus, adding a possibility to control the timer resolution is a good and small enough tradeoff for safety and future.
This commit is contained in:
parent
f09c012ebe
commit
c3717d9aec
13
UPGRADING
13
UPGRADING
@ -104,7 +104,8 @@ Core:
|
||||
adjustable and is not related to wall clock or time of day. The timers
|
||||
are available under Linux, FreeBSD, Windows, Mac, SunOS, AIX and their
|
||||
derivatives. If no required timers are provided by a corresponding
|
||||
platform, the function returns false.
|
||||
platform, the function returns false. See also the description for the
|
||||
hrtime.resolution INI directive for further configuration details.
|
||||
|
||||
Date:
|
||||
. Added the DateTime::createFromImmutable() method, which mirrors
|
||||
@ -189,6 +190,16 @@ PGSQL:
|
||||
. This INI directive has been removed. The value has already been ignored
|
||||
since PHP 5.3.0.
|
||||
|
||||
- hrtime.resolution
|
||||
. This INI directive is PHP_INI_SYSTEM and controls the precision of the
|
||||
timestamps delivered by hrtime(). It expects a positive number of
|
||||
nanoseconds, to which the timestamp is rounded. For example, if the max
|
||||
desired precision of the timestamp is 20us, the INI value would be 20000
|
||||
and the timestamp is rounded to the next 20us. If the INI value is zero
|
||||
(default), the measurement is returned without change. Note, that the
|
||||
timestamp itself stays monotonic. The provided precision still affects,
|
||||
in how far two adjacent timestamps can be distinquished.
|
||||
|
||||
========================================
|
||||
12. Windows Support
|
||||
========================================
|
||||
|
@ -56,6 +56,8 @@ static mach_timebase_info_data_t _timerlib_info;
|
||||
#endif
|
||||
|
||||
#define NANO_IN_SEC 1000000000
|
||||
|
||||
static php_hrtime_t _timer_resolution = 0;
|
||||
/* }}} */
|
||||
|
||||
static int _timer_init()
|
||||
@ -100,9 +102,32 @@ static int _timer_init()
|
||||
return 0;
|
||||
}/*}}}*/
|
||||
|
||||
/* {{{ */
|
||||
|
||||
/* {{{ ini */
|
||||
static PHP_INI_MH(OnUpdateResolution)
|
||||
{
|
||||
zend_long _val;
|
||||
|
||||
ZEND_ATOL(_val, ZSTR_VAL(new_value));
|
||||
|
||||
if (_val < 0) {
|
||||
return FAILURE;
|
||||
}
|
||||
_timer_resolution = _val;
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
PHP_INI_BEGIN()
|
||||
PHP_INI_ENTRY("hrtime.resolution", "0", PHP_INI_SYSTEM, OnUpdateResolution)
|
||||
PHP_INI_END()
|
||||
/* }}} */
|
||||
|
||||
/* {{{ MINIT */
|
||||
PHP_MINIT_FUNCTION(hrtime)
|
||||
{
|
||||
REGISTER_INI_ENTRIES();
|
||||
|
||||
if (0 > _timer_init()) {
|
||||
php_error_docref(NULL, E_WARNING, "Failed to initialize high-resolution timer");
|
||||
return FAILURE;
|
||||
@ -176,6 +201,10 @@ PHP_FUNCTION(hrtime)
|
||||
Z_PARAM_BOOL(get_as_num)
|
||||
ZEND_PARSE_PARAMETERS_END();
|
||||
|
||||
if (_timer_resolution) {
|
||||
t = (php_hrtime_t)(t / _timer_resolution) * _timer_resolution;
|
||||
}
|
||||
|
||||
if (UNEXPECTED(get_as_num)) {
|
||||
PHP_RETURN_HRTIME(t);
|
||||
} else {
|
||||
|
15
ext/standard/tests/hrtime/hrtime_ini.phpt
Normal file
15
ext/standard/tests/hrtime/hrtime_ini.phpt
Normal file
@ -0,0 +1,15 @@
|
||||
--TEST--
|
||||
Ensure hrtime.resolution is not changeable from script
|
||||
--INI--
|
||||
hrtime.resolution=1000000
|
||||
--FILE--
|
||||
<?php
|
||||
var_dump(
|
||||
ini_set("hrtime.resolution", 0),
|
||||
ini_get("hrtime.resolution")
|
||||
);
|
||||
?>
|
||||
--EXPECT--
|
||||
bool(false)
|
||||
string(7) "1000000"
|
||||
|
34
ext/standard/tests/hrtime/hrtime_resolution.phpt
Normal file
34
ext/standard/tests/hrtime/hrtime_resolution.phpt
Normal file
@ -0,0 +1,34 @@
|
||||
--TEST--
|
||||
Test hrtime() reduced resolution
|
||||
--INI--
|
||||
hrtime.resolution=20000
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
/* This may fail on a very slow machine. Two subsequent timestamp
|
||||
probes shoul lay in the configured interval. */
|
||||
|
||||
$d0 = hrtime(true) - hrtime(true);
|
||||
$d0 = abs($d0);
|
||||
|
||||
$t0 = hrtime();
|
||||
$t1 = hrtime();
|
||||
$d1 = ($t1[0] - $t0[0]) * 1000000000 + $t1[1] - $t0[1];
|
||||
|
||||
if (0 == $d0 || 20000 == $d0) {
|
||||
echo "PASS hrtime(true)\n";
|
||||
} else {
|
||||
echo "Two subsequent hrtime(true) calls gave $d0\n";
|
||||
}
|
||||
|
||||
if (0 == $d1 || 20000 == $d1) {
|
||||
echo "PASS hrtime()\n";
|
||||
} else {
|
||||
echo "Two subsequent hrtime() calls gave $d1\n";
|
||||
}
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
PASS hrtime(true)
|
||||
PASS hrtime()
|
||||
|
Loading…
Reference in New Issue
Block a user