diff options
| author | Victor Stinner <victor.stinner@gmail.com> | 2016-06-07 09:25:43 (GMT) | 
|---|---|---|
| committer | Victor Stinner <victor.stinner@gmail.com> | 2016-06-07 09:25:43 (GMT) | 
| commit | 9ff9cbd600f0290df20c73a31a9c4d43f3cf61d6 (patch) | |
| tree | 7dfb6ce341c9fb0b9220d046f2e63805b773e16d /Python/random.c | |
| parent | cb3a581636135556429b2036663e91c043c2bfd8 (diff) | |
| parent | dddf4849ec1750ca02d03b9772eff7141ba626f3 (diff) | |
| download | cpython-9ff9cbd600f0290df20c73a31a9c4d43f3cf61d6.zip cpython-9ff9cbd600f0290df20c73a31a9c4d43f3cf61d6.tar.gz cpython-9ff9cbd600f0290df20c73a31a9c4d43f3cf61d6.tar.bz2  | |
Merge 3.5 (os.urandom)
Diffstat (limited to 'Python/random.c')
| -rw-r--r-- | Python/random.c | 24 | 
1 files changed, 21 insertions, 3 deletions
diff --git a/Python/random.c b/Python/random.c index 839d7ad..ef3a4cd 100644 --- a/Python/random.c +++ b/Python/random.c @@ -6,6 +6,9 @@  #  ifdef HAVE_SYS_STAT_H  #    include <sys/stat.h>  #  endif +#  ifdef HAVE_LINUX_RANDOM_H +#    include <linux/random.h> +#  endif  #  ifdef HAVE_GETRANDOM  #    include <sys/random.h>  #  elif defined(HAVE_GETRANDOM_SYSCALL) @@ -122,9 +125,13 @@ py_getrandom(void *buffer, Py_ssize_t size, int raise)      /* Is getrandom() supported by the running kernel?       * Need Linux kernel 3.17 or newer, or Solaris 11.3 or newer */      static int getrandom_works = 1; -    /* Use non-blocking /dev/urandom device. On Linux at boot, the getrandom() -     * syscall blocks until /dev/urandom is initialized with enough entropy. */ -    const int flags = 0; + +    /* getrandom() on Linux will block if called before the kernel has +     * initialized the urandom entropy pool. This will cause Python +     * to hang on startup if called very early in the boot process - +     * see https://bugs.python.org/issue26839. To avoid this, use the +     * GRND_NONBLOCK flag. */ +    const int flags = GRND_NONBLOCK;      int n;      if (!getrandom_works) @@ -168,6 +175,17 @@ py_getrandom(void *buffer, Py_ssize_t size, int raise)                  getrandom_works = 0;                  return 0;              } +            if (errno == EAGAIN) { +                /* If we failed with EAGAIN, the entropy pool was +                 * uninitialized. In this case, we return failure to fall +                 * back to reading from /dev/urandom. +                 * +                 * Note: In this case the data read will not be random so +                 * should not be used for cryptographic purposes. Retaining +                 * the existing semantics for practical purposes. */ +                getrandom_works = 0; +                return 0; +            }              if (errno == EINTR) {                  if (PyErr_CheckSignals()) {  | 
