Inject entropy from the disk using the bootloader and similar problem fixed in Python
Inject entropy from the disk using the bootloader and similar problem fixed in Python
Posted Sep 27, 2019 21:07 UTC (Fri) by vstinner (subscriber, #42675)Parent article: Fixing getrandom()
OpenBSD fixed this boot issue: their bootloader loads entropy from disk, and the installer collects enough entropy. It doesn't cover all cases (read-only livecd, systems with no entropy source to feed new entropy, etc.), but it fix the "lack of entropy at boot" issue for the common case.
--
In 2015, a systemd script used Python to compute a hash. Python blocked on getrandom() at boot.
When the bug has been reported, a very long discussion started on the bug tracker, continued on the python-dev mailing list. A new mailing list has been created just to discuss this bug :-)
At the end, we decided to fallback on /dev/urandom if getrandom() blocks, to initialize the "secret hash seed". This secret is used to randomize the dictionary hash function, to reduce the disk of a denial of attack on dictionaries.
Moreover, the os.urandom() function has been modified on Linux (and Solaris: systems providing getrandom() syscall/function) to block (on purpose) until the system collected enough entropy.
Calling os.getrandom(1, os.GRND_NONBLOCK) can be used to check if getrandom() is going to block or not. Some people asked for this feature, but I'm not sure that it's really used in practice.
The https://www.python.org/dev/peps/pep-0524/ describes the issue and fix.
--
Python was an early adopter of getrandom() syscall, before it was exposed as a function in the glibc ;-)
Python keeps a file descriptor open on /dev/urandom for best performance. Some badly written applications close the file descriptor by mistake, so Python detects if the file descriptor changed (compare st_dev and st_ino) to workaround application bugs. Moreover, there is no lock on the file descriptor for best performance, which requires to detect when two threads open the file "at the same time".
So well, getrandom() avoids all these issues.