summaryrefslogtreecommitdiffstats
path: root/Python/random.c
diff options
context:
space:
mode:
authorVictor Stinner <victor.stinner@gmail.com>2016-06-07 09:25:43 (GMT)
committerVictor Stinner <victor.stinner@gmail.com>2016-06-07 09:25:43 (GMT)
commit9ff9cbd600f0290df20c73a31a9c4d43f3cf61d6 (patch)
tree7dfb6ce341c9fb0b9220d046f2e63805b773e16d /Python/random.c
parentcb3a581636135556429b2036663e91c043c2bfd8 (diff)
parentdddf4849ec1750ca02d03b9772eff7141ba626f3 (diff)
downloadcpython-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.c24
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()) {