On 17.05.2016 08:28, Vincent Veyron wrote:
On Mon, 16 May 2016 22:45:14 +0000
"Bruce Johnson" <john...@pharmacy.arizona.edu> wrote:
I don’t think it would be likely for Vincent to ever see this once, let alone
have it rise to the issue of a problem if it were strictly about non-randomness
of the rand() function.
Indeed : I also use the function to generate cookies; the strings are stored in a
database table with a primary key on the token ; running 'ab -c 4 -n 4000
"http://my/url/here"' 3 times yields 12 000 unique keys on a functional server.
The machine where the error showed up can't get two different strings in a row.
It's a backup server, so I'm the only one using it for test purposes, which is
why I did not notice the error before; it may have been present for a long time.
Below is what is installed on each machine, the first one (arsene) being the
faulty one; it is a rather old Dell desktop, the others are dedicated servers
in datacenters, such as kimsufi.com, online.net. Everything is on bare metal,
and incidentally not as uniform as I thought :-(
reload-perl is installed but disabled in apache2.conf
perl -v on the faulty machine (arsene) :
This is perl 5, version 20, subversion 2 (v5.20.2) built for
i586-linux-gnu-thread-multi-64int
perl -v on the good ones :
This is perl 5, version 20, subversion 2 (v5.20.2) built for
x86_64-linux-gnu-thread-multi
arsene (cpuinfo : Intel(R) Core(TM)2 Duo CPU E7500 @ 2.93GHz)
ii apache2 2.4.10-10+deb8u4 i386 Apache
HTTP Server
ii apache2-bin 2.4.10-10+deb8u4 i386 Apache
HTTP Server (modules and other binary files)
ii apache2-data 2.4.10-10+deb8u4 all Apache
HTTP Server (common files)
ii apache2-mpm-prefork 2.4.10-10+deb8u4 i386
transitional prefork MPM package for apache2
ii apache2-utils 2.4.10-10+deb8u4 i386 Apache
HTTP Server (utility programs for web servers)
ii apache2.2-common 2.4.10-10+deb8u4 i386
Transitional package for apache2
ii libapache2-mod-apreq2 2.13-4+b1 i386
generic Apache request library - Apache module
ii libapache2-mod-perl2 2.0.9~1624218-2+deb8u1 i386
Integration of perl with the Apache2 web server
ii libapache2-reload-perl 0.12-3 all module
for reloading Perl modules when changed on disk
ii libapache2-request-perl 2.13-4+b1 i386
generic Apache request library - Perl modules
kimsufi (cpuinfo : Intel(R) Atom(TM) CPU N2800 @ 1.86GHz)
ii apache2 2.4.10-10+deb8u4 amd64 Apache
HTTP Server
ii apache2-bin 2.4.10-10+deb8u4 amd64 Apache
HTTP Server (modules and other binary files)
ii apache2-data 2.4.10-10+deb8u4 all Apache
HTTP Server (common files)
ii apache2-mpm-prefork 2.4.10-10+deb8u4 amd64
transitional prefork MPM package for apache2
ii apache2-utils 2.4.10-10+deb8u4 amd64 Apache
HTTP Server (utility programs for web servers)
ii apache2.2-common 2.4.10-10+deb8u4 amd64
Transitional package for apache2
ii libapache2-mod-apreq2 2.13-4+b1 amd64
generic Apache request library - Apache module
ii libapache2-mod-perl2 2.0.9~1624218-2+deb8u1 amd64
Integration of perl with the Apache2 web server
ii libapache2-reload-perl 0.12-3 all module
for reloading Perl modules when changed on disk
ii libapache2-request-perl 2.13-4+b1 amd64
generic Apache request library - Perl modules
online (cpuinfo : VIA Nano processor U2250 (1.6GHz Capable))
ii apache2 2.4.10-10+deb8u4 amd64 Apache HTTP
Server
ii apache2-bin 2.4.10-10+deb8u4 amd64 Apache HTTP
Server (modules and other binary files)
ii apache2-data 2.4.10-10+deb8u4 all Apache HTTP
Server (common files)
ii apache2-mpm-prefork 2.4.10-10+deb8u4 amd64 transitional
prefork MPM package for apache2
ii apache2-utils 2.4.10-10+deb8u4 amd64 Apache HTTP
Server (utility programs for web servers)
ii libapache2-mod-apreq2 2.13-4+b1 amd64 generic
Apache request library - Apache module
ii libapache2-mod-perl2 2.0.9~1624218-2+deb8u1 amd64 Integration
of perl with the Apache2 web server
ii libapache2-request-perl 2.13-4+b1 amd64 generic
Apache request library - Perl modules
ovh (cpuinfo : Intel(R) Celeron(R) CPU 220 @ 1.20GHz)
ii apache2 2.4.10-10+deb8u4 amd64 Apache HTTP
Server
ii apache2-bin 2.4.10-10+deb8u4 amd64 Apache HTTP
Server (modules and other binary files)
ii apache2-data 2.4.10-10+deb8u4 all Apache HTTP
Server (common files)
ii apache2-utils 2.4.10-10+deb8u4 amd64 Apache HTTP
Server (utility programs for web servers)
ii libapache2-mod-apreq2 2.13-4+b1 amd64 generic
Apache request library - Apache module
ii libapache2-mod-perl2 2.0.9~1624218-2+deb8u1 amd64 Integration
of perl with the Apache2 web server
ii libapache2-reload-perl 0.12-3 all module for
reloading Perl modules when changed on disk
ii libapache2-request-perl 2.13-4+b1 amd64 generic
Apache request library - Perl modules
I don't see above any signifiant difference in configuration between the servers, apart
from the fact that the "faulty" server runs a 64-bit version of perl.
But I still wonder if this is the issue :
http://perldoc.perl.org/functions/srand.html
says :
"If srand() is not called explicitly, it is called implicitly without a parameter at the
first use of the rand operator. However, there are a few situations where programs are
likely to want to call srand. One is for generating predictable results, generally for
testing or debugging. There, you use srand($seed), with the same $seed each time. Another
case is that you may want to call srand() after a fork() to avoid child processes sharing
the same seed value as the parent (and consequently each other)."
This would tend to imply that the "real" seed used initially by srand() (such as when it
is called implicitly at the first call to rand()), is something inside the perl
interpreter itself. In a pre-fork configuration, the main Apache process starts first,
and loads a perl interpreter. Then this main Apache process is forked into nn Apache
children processes. Which means that the initial copies of the perl interpreter, in each
child, are also identical.
The main Apache process never runs any request (it just passes them to a child, which does
run the request), so its copy of the perl interpreter remains "pristine", as it was before
the first fork.
If at some point there are not enough children alive, the main process forks again to
create a new child.
So basically all children, present and future, start with the same perl.
And thus with the same whatever-it-is that is the seed of the first srand() (implicitly
called by the first rand()).
So, unless they all do explicitly call srand() once with each a different seed, each child
does generate exactly the same sequence of responses to successive rand() calls.
In other words, on any given machine, the Nth un-keyed request hitting one particular
Apache child, will generate the same key as the Nth un-keyed request hitting any other
child (assuming rand() is not used anywhere else).
(By "un-keyed request", I mean one which triggers the key-generating
instruction).
(and N including perhaps also the requests which trigger similar calls to rand to generate
a cookie, if they call rand() the same number of times (32)).
Except that..
The machine where the problem shows up so quickly, is running a 64-bit perl, while the
others are running 32-bit perls.
Now I also found this :
http://rabexc.org/posts/randomizing-should-be-easy-right-oh
I am not sure that I really understand this all the way down, but would this not be a
suspect in a case where the behaviour seems different between one 64-bit machine, and a
bunch of 32-bit ones ?
This being said, it still looks to me as if the current code is flawed on *all* machines,
and *will* repeat keys quite often. It just depends again on the exact sequence of
requests hitting a specific Apache, and the other parameters I mentioned before.
I still believe that the fact that it does not *seem* to happen, is just due to the
inherent randomness of these other factors on the production machines.