GH-1076: Fix use of getrandom()

The availability and use of getrandom() actually caused unrandom and
deterministic results in terms of Zeek's random number generation.
This commit is contained in:
Jon Siwek 2020-07-21 14:24:50 -07:00
parent d7425b90d7
commit dba764386b
3 changed files with 52 additions and 10 deletions

View file

@ -1105,16 +1105,15 @@ void init_random_seed(const char* read_file, const char* write_file,
else if ( use_empty_seeds ) else if ( use_empty_seeds )
seeds_done = true; seeds_done = true;
if ( ! seeds_done )
{
#ifdef HAVE_GETRANDOM #ifdef HAVE_GETRANDOM
if ( ! seeds_done ) // getrandom() guarantees reads up to 256 bytes are always successful,
{ assert(sizeof(buf) < 256);
ssize_t nbytes = getrandom(buf.data(), sizeof(buf), 0); auto nbytes = getrandom(buf.data(), sizeof(buf), 0);
seeds_done = nbytes == ssize_t(sizeof(buf)); assert(nbytes == sizeof(buf));
} pos += nbytes / sizeof(uint32_t);
#endif #else
if ( ! seeds_done )
{
// Gather up some entropy. // Gather up some entropy.
gettimeofday((struct timeval *)(buf.data() + pos), 0); gettimeofday((struct timeval *)(buf.data() + pos), 0);
pos += sizeof(struct timeval) / sizeof(uint32_t); pos += sizeof(struct timeval) / sizeof(uint32_t);
@ -1141,9 +1140,10 @@ void init_random_seed(const char* read_file, const char* write_file,
// systems due to a lack of entropy. // systems due to a lack of entropy.
errno = 0; errno = 0;
} }
#endif
if ( pos < KeyedHash::SEED_INIT_SIZE ) if ( pos < KeyedHash::SEED_INIT_SIZE )
reporter->FatalError("Could not read enough random data from /dev/urandom. Wanted %d, got %lu", KeyedHash::SEED_INIT_SIZE, pos); reporter->FatalError("Could not read enough random data. Wanted %d, got %lu", KeyedHash::SEED_INIT_SIZE, pos);
if ( ! seed ) if ( ! seed )
{ {

View file

@ -0,0 +1 @@
F

View file

@ -1,13 +1,19 @@
# #
# @TEST-EXEC: zeek -b %INPUT >out # @TEST-EXEC: zeek -b %INPUT >out
# @TEST-EXEC: zeek -b %INPUT do_seed=F >out.2 # @TEST-EXEC: zeek -b %INPUT do_seed=F >out.2
# @TEST-EXEC: unset ZEEK_SEED_FILE && zeek -b %INPUT real_random=T >out.3
# @TEST-EXEC: btest-diff out # @TEST-EXEC: btest-diff out
# @TEST-EXEC: btest-diff out.2 # @TEST-EXEC: btest-diff out.2
# @TEST-EXEC: btest-diff out.3
const do_seed = T &redef; const do_seed = T &redef;
const real_random = F &redef;
event zeek_init() event zeek_init()
{ {
if ( real_random )
return;
local a = rand(1000); local a = rand(1000);
local b = rand(1000); local b = rand(1000);
local c = rand(1000); local c = rand(1000);
@ -27,3 +33,38 @@ event zeek_init()
print e; print e;
print f; print f;
} }
event zeek_init() &priority=-10
{
if ( ! real_random )
return;
local v1: vector of count = vector();
local v2: vector of count = vector();
local i = 0;
while ( i < 20 )
{
v1 += rand(65535);
i += 1;
}
i = 0;
while ( i < 20 )
{
v2 += rand(65535);
i += 1;
}
# Note: this is expected to be F with high probability, but
# technically could all be the same because, well, that's a
# valid "random" sequence, too
print all_set(v1 == v2);
if ( all_set(v1 == v2) )
{
print v1;
print v2;
}
}