arc4random

Florian Weimer fweimer@redhat.com
Sat Sep 30 06:22:00 GMT 2017


On 09/30/2017 01:58 AM, Zack Weinberg wrote:

>> I think I found a way to do full fork protection even without
>> MADV_WIPEONFORK, using a global counter in a MAP_SHARED segment. Reseeding
>> is still needed to deal with a counter overflow on 32-bit architectures, and
>> there is some overhead by the globally shared counter, but I think it is
>> superior to all approaches I've seen so far (and it does not require a fork
>> handler or a system call for every random number generation).
> 
> Is the idea that after a fork, processes may share RNG state but they
> see each others' counter increments so they won't return the same
> random bits from paired calls?  Kind of like how it would work for
> multiple threads with a shared but atomically accessed RNG state?

Exactly.  There's also a per-thread cache of an output block from the 
underlying DRBG, but without MADV_WIPEONFORK, that's invalidated if 
arc4random is called from multiple threads (because the global counter 
does not match the expected value anymore).  But at least it's not 
necessary to acquire a lock around the actual cryptographic operation.

But all this is only possible for 64-bit atomics.  If those are not 
available, I'm not sure what we can do.  The initial implementation will 
have a 32-bit counter in the shared page and a lock (not shared across 
processes) which is acquired around the entire arc4random operation.  If 
the 32-bit counter overflows, we need to replace the page with the 
global state with a new one (using MAP_FIXED) and reinitialize the 
secrets.  I don't think we can use any of the usual techniques for 
building a >32-bit counter from two 32-bit values because they rely on 
flag bits and waiting, but the other process can die at any time, and a 
waiting operation would get stuck at that point.

Thanks,
Florian



More information about the Libc-alpha mailing list