4 ms·
> Another option is to store the seed in a MAP_SHARED segment. I assume you mean MAP_PRIVATE? But that doesn't work. MAP_PRIVATE pages are copied to a fork.
by daurnimator 11y ago
> Another option is to store the seed in a MAP_SHARED segment.
I assume you mean MAP_PRIVATE?
But that doesn't work. MAP_PRIVATE pages are copied to a fork.
- xroche 11y agoUnless `madvise(ptr, size, MADV_DONTFORK)' is used. But in this case you have no information at all on the region (which may have been mapped by another library), but I might not have understood the initial OP suggestion.
- xroche 11y agoForget it - OP wanted to have a shared anonymous pool, obviously (but in this case, using shm_open()+mmap() could do the trick)
- geocar 11y agoNo, I meant MAP_SHARED. That way the seed is shared across all forks and will only cause problems if the PRNG is being used as a cipher. However there's another trick. If you have two counters: One in MAP_PRIVATE and one in MAP_SHARED you can detect the unsafe scenario by incrementing each counter and verifying lockstep. If the counters mismatch, you've been forked: unmap and map new pages, and do whatever post-fork "reinitialisation" that is required.
- agwa 11y agoThat doesn't work because there's a race condition - if both processes increment the MAP_SHARED counter at the same time, they could end up seeing the same value and not think that a fork has occurred.
- geocar 11y agoUse an atomic increment (e.g. lock xadd).
- agwa 11y agoThat's architecture-specific, which isn't nice. Also, the counters would need to be 64 bits so that wraparound isn't a concern. Do all architectures even have an atomic 64 bit increment?
- geocar 11y agoWhat, and linux isn't architecture-specific? The counters don't need to be 64-bits: Programs don't need a random number in one process and the 4 billionth only.
- agwa 11y ago> What, and linux isn't architecture-specific? I have no clue what point you're trying to make. > The counters don't need to be 64-bits: Programs don't need a random number in one process and the 4 billionth only. If this is going to be used for a CSPRNG, you have to take into account adversarial conditions. A 32 bit counter leaves insufficient safety margin: it's conceivable an attacker could induce an application to generate so many random numbers that the counter wraps around, causing another process to generate a duplicate random number. It may seem unlikely, but time after time security researchers have demonstrated that attacks previously considered "unlikely" are possible.
- geocar 11y agoNo, a 64-bit atomic add isn't required. Smaller atomic adds can be used just fine with a double-wide number.
- daurnimator 11y agoBut what if you have more than one child/grandchildren/siblings. Each parent+child pair would need their own MAP_SHARED+MAP_PRIVATE pair. I'm not sure if this is workable...
- geocar 11y agoNo they don't. 2 pages are used for each child that needs a random number from the shared seed, during the scope of the parent needing the seed. This is insignificant, and one of the pages can contain the seed. The Right Thing is to have a "prng_init()" routine, since the program that fork()s will know what it needs to do.