Edit report at https://bugs.php.net/bug.php?id=71915&edit=1
ID: 71915
Updated by: bukka@php.net
Reported by: mathieuk at gmail dot com
Summary: openssl_random_pseudo_bytes is not "fork-safe"
Status: Assigned
Type: Bug
Package: OpenSSL related
Operating System: any
PHP Version: 5.6.19
Assigned To: bukka
Block user comment: N
Private report: N
New Comment:
Yeah there seems to be missing global init which should reset the value for each request
(PHP_GINIT_FUNCTION). Then it should be fine and the entropy would be added for the first call of
the openssl_random_pseudo_bytes in the request. It means it can be added multiple time if the same
process is used for more requests (fpm) which I'm not sure is ideal but might not be an issue.
Again I might be wrong.
Previous Comments:
------------------------------------------------------------------------
[2016-03-29 18:54:12] krakjoe@php.net
Well, COW duplicated ... the same data whatever ...
------------------------------------------------------------------------
[2016-03-29 18:53:04] krakjoe@php.net
It's not sensible to use module globals, these are duplicated on fork.
So if the parent process has already called a function that results in reseed, or poll, the child
process will not make the call ...
------------------------------------------------------------------------
[2016-03-29 18:40:47] bukka@php.net
I think that calling RAND_poll on the first call openssl_random_pseudo_bytes in each request is
quite overkill and it might cause some perf regressions. RAND_poll is an expensive call.
Wouldn't be enough to use RAND_seed / RAND_add (it's the same in the default rand method)
with PID for example.
P.S. I'm not a rand expert but hope that it shouldn't have any impact on randomness. But
might be wrong. :) In any case RAND_poll seems just too much...
------------------------------------------------------------------------
[2016-03-29 10:00:46] mathieuk at gmail dot com
Description:
------------
In https://github.com/ramsey/uuid/issues/80
it was determined that under specific circumstances openssl_random_pseudo_bytes may generate
duplicate random values when using a forked process model (like Apache2 prefork MPM or FastCGI)
because OpenSSL seeds its random number generator the first time with a blob of data from
/dev/u?random (depends on config) and then only mixes in the current pid ( pre 20 sept 2013 ) and
the current time ( post 20 sept 2013 ) for each call to RAND_bytes().
This has happened with other projects, like Android, see http://emboss.github.io/blog/2013/08/21/openssl-prng-is-not-really-fork-safe/
. OpenSSL documents it not being "fork-safe" here: https://wiki.openssl.org/index.php/Random_fork-safety.
One of the mitigations suggested is calling RAND_poll() after fork(). I've tried to implement
such an approach in https://github.com/php/php-src/commit/afbe15c7e7d2fe650e08f48d62fc4f7928bab695
. It's probably incomplete (maybe reinit_rng() should be called on other functions too) but I
wanted to get feedback first before spending more time on it.
Test script:
---------------
https://gist.github.com/mathieuk/63cc6479734b820340b6
------------------------------------------------------------------------
--
Edit this bug report at https://bugs.php.net/bug.php?id=71915&edit=1