getrandom() syscalls and Python runtime binary portability
Hi folks, Working on an update to PEP 522, I realised while poking around in sysconfig for the HAVE_GETRANDOM_SYSCALL flag that only checking for whether or not the syscall had been available at buildtime would be potentially problematic - it means that a Python built against a newer Linux kernel (e.g. Ubuntu 16.04, Fedora 24) may do the wrong thing when run on an older kernel that hasn't had the new syscall backported (e.g. Ubuntu 14.04, RHEL 7.2, CentOS 7.1511). That's something that can easily happen with containers, or any other case of bundling the language runtime with the application executable. The actual code behind os.urandom already deals with this case correctly (see the ENOSYS reference in py_getrandom at [1]), but it means there really is no way for pure Python code running against an older kernel to tell whether a successful os.urandom() call was because the system RNG was ready or because the kernel is old. So regardless of whether we go with the blocking-by-default or raise-BlockingIOError strategy, we should also define what we want the interpreter to do in the ENOSYS case (for PEP 522, I wanted to warn about it in the new secrets.wait_for_system_rng() function, but at least for now I'm going to settle for letting the SipHash initialisation warn about it, the same way it would for a lack of entropy) This is actually the best argument I've seen so far for exposing os.getrandom() directly: unlike os.urandom(), we could allow a new os.getrandom() API to raise NotImplementedError if the running kernel doesn't provide the getrandom() syscall. Having such an API available would then let secrets.wait_for_system_rng() more reliably check whether or not the system RNG was ready before falling back on a potentially blocking read of /dev/random. Cheers, Nick. [1] https://hg.python.org/cpython/file/default/Python/random.c#l119 -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia
participants (1)
-
Nick Coghlan