read_random() is used, mostly without error checking, in a lot of very
sensitive places in the kernel -- including seeding the widely used
arc4random(9)!
Most uses, especially arc4random(9), should block until the device is seeded
rather than proceeding with a bogus or empty seed. I did not spy any
obvious kernel consumers where blocking would be inappropriate. In some
instances, I replaced raw read_random(9) invocations with arc4random_buf(9)
or similar.
One caveat of this change is that the kern.arandom sysctl no longer returns
zero bytes immediately if the random device is not seeded. This means that
FreeBSD-specific userspace applications which attempted to handle an
unseeded random device may be broken by this change. If such behavior is
needed, it can be replaced by the more portable getrandom(2) GRND_NONBLOCK
option.
On any typical FreeBSD system, entropy is persisted on read/write media and
used to seed the random device very early in boot, and blocking is never a
problem anyway.
This change primarily impacts the behavior of /dev/random on embedded
systems with read-only media. We toggle the default from 'charge on blindly
with no entropy' to 'block indefinitely.' This default is the safer, but
less may cause frustration. Embedded system designers using FreeBSD who
cannot provide a writable media for entropy persistence and re-seeding are
encouraged to design their own initial seeding and/or key generation delay
scheme to fit their specific needs. Early entropy can be fed from any
loader or by early userspace writing to the /dev/random device (as root).
(For those who prefer a weak system random device, it can be fake-started by
dding /dev/zero into /dev/random. This is strongly discouraged.)
I attempted to document this change in random.4 and random.9 and ran into a
bunch of out-of-date or irrelevant or inaccurate content and ended up
rototilling those documents more than I intended to. Sorry. I think
they're in a better state now.
PR: 230875