summaryrefslogtreecommitdiffstats
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
parentcb3a581636135556429b2036663e91c043c2bfd8 (diff)
parentdddf4849ec1750ca02d03b9772eff7141ba626f3 (diff)
downloadcpython-9ff9cbd600f0290df20c73a31a9c4d43f3cf61d6.zip
cpython-9ff9cbd600f0290df20c73a31a9c4d43f3cf61d6.tar.gz
cpython-9ff9cbd600f0290df20c73a31a9c4d43f3cf61d6.tar.bz2
Merge 3.5 (os.urandom)
-rw-r--r--Doc/library/os.rst13
-rw-r--r--Misc/ACKS1
-rw-r--r--Misc/NEWS4
-rw-r--r--Python/random.c24
-rwxr-xr-xconfigure8
-rw-r--r--configure.ac7
-rw-r--r--pyconfig.h.in3
7 files changed, 48 insertions, 12 deletions
diff --git a/Doc/library/os.rst b/Doc/library/os.rst
index 4ed01dd..deabaeb 100644
--- a/Doc/library/os.rst
+++ b/Doc/library/os.rst
@@ -3768,14 +3768,21 @@ Miscellaneous Functions
This function returns random bytes from an OS-specific randomness source. The
returned data should be unpredictable enough for cryptographic applications,
- though its exact quality depends on the OS implementation. On a Unix-like
- system this will query ``/dev/urandom``, and on Windows it will use
- ``CryptGenRandom()``. If a randomness source is not found,
+ though its exact quality depends on the OS implementation.
+
+ On Linux, ``getrandom()`` syscall is used if available and the urandom
+ entropy pool is initialized (``getrandom()`` does not block).
+ On a Unix-like system this will query ``/dev/urandom``. On Windows, it
+ will use ``CryptGenRandom()``. If a randomness source is not found,
:exc:`NotImplementedError` will be raised.
For an easy-to-use interface to the random number generator
provided by your platform, please see :class:`random.SystemRandom`.
+ .. versionchanged:: 3.5.2
+ On Linux, if ``getrandom()`` blocks (the urandom entropy pool is not
+ initialized yet), fall back on reading ``/dev/urandom``.
+
.. versionchanged:: 3.5
On Linux 3.17 and newer, the ``getrandom()`` syscall is now used
when available. On OpenBSD 5.6 and newer, the C ``getentropy()``
diff --git a/Misc/ACKS b/Misc/ACKS
index 702cd92..c596e31 100644
--- a/Misc/ACKS
+++ b/Misc/ACKS
@@ -201,6 +201,7 @@ Ian Bruntlett
Floris Bruynooghe
Matt Bryant
Stan Bubrouski
+Colm Buckley
Erik de Bueger
Jan-Hein Bührman
Lars Buitinck
diff --git a/Misc/NEWS b/Misc/NEWS
index 7330ad5..b8c643f 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -27,6 +27,10 @@ Core and Builtins
Library
-------
+- Issue #26839: On Linux, :func:`os.urandom` now calls ``getrandom()`` with
+ ``GRND_NONBLOCK`` to fall back on reading ``/dev/urandom`` if the urandom
+ entropy pool is not initialized yet. Patch written by Colm Buckley.
+
- Issue #23883: Added missing APIs to __all__ to match the documented APIs
for the following modules: cgi, mailbox, mimetypes, plistlib and smtpd.
Patches by Jacek Kołodziej.
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()) {
diff --git a/configure b/configure
index 17a966a..da4a59a 100755
--- a/configure
+++ b/configure
@@ -2876,6 +2876,7 @@ fi
ac_config_headers="$ac_config_headers pyconfig.h"
+
ac_aux_dir=
for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do
if test -f "$ac_dir/install-sh"; then
@@ -7568,7 +7569,7 @@ sys/param.h sys/select.h sys/sendfile.h sys/socket.h sys/statvfs.h \
sys/stat.h sys/syscall.h sys/sys_domain.h sys/termio.h sys/time.h \
sys/times.h sys/types.h sys/uio.h sys/un.h sys/utsname.h sys/wait.h pty.h \
libutil.h sys/resource.h netpacket/packet.h sysexits.h bluetooth.h \
-bluetooth/bluetooth.h linux/tipc.h spawn.h util.h alloca.h endian.h \
+bluetooth/bluetooth.h linux/tipc.h linux/random.h spawn.h util.h alloca.h endian.h \
sys/endian.h
do :
as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
@@ -16431,12 +16432,13 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
#include <unistd.h>
#include <sys/syscall.h>
+ #include <linux/random.h>
int main() {
char buffer[1];
const size_t buflen = sizeof(buffer);
- const int flags = 0;
- /* ignore the result, Python checks for ENOSYS at runtime */
+ const int flags = GRND_NONBLOCK;
+ /* ignore the result, Python checks for ENOSYS and EAGAIN at runtime */
(void)syscall(SYS_getrandom, buffer, buflen, flags);
return 0;
}
diff --git a/configure.ac b/configure.ac
index 0b026d0..1fbc655 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1881,7 +1881,7 @@ sys/param.h sys/select.h sys/sendfile.h sys/socket.h sys/statvfs.h \
sys/stat.h sys/syscall.h sys/sys_domain.h sys/termio.h sys/time.h \
sys/times.h sys/types.h sys/uio.h sys/un.h sys/utsname.h sys/wait.h pty.h \
libutil.h sys/resource.h netpacket/packet.h sysexits.h bluetooth.h \
-bluetooth/bluetooth.h linux/tipc.h spawn.h util.h alloca.h endian.h \
+bluetooth/bluetooth.h linux/tipc.h linux/random.h spawn.h util.h alloca.h endian.h \
sys/endian.h)
AC_HEADER_DIRENT
AC_HEADER_MAJOR
@@ -5246,12 +5246,13 @@ AC_LINK_IFELSE(
AC_LANG_SOURCE([[
#include <unistd.h>
#include <sys/syscall.h>
+ #include <linux/random.h>
int main() {
char buffer[1];
const size_t buflen = sizeof(buffer);
- const int flags = 0;
- /* ignore the result, Python checks for ENOSYS at runtime */
+ const int flags = GRND_NONBLOCK;
+ /* ignore the result, Python checks for ENOSYS and EAGAIN at runtime */
(void)syscall(SYS_getrandom, buffer, buflen, flags);
return 0;
}
diff --git a/pyconfig.h.in b/pyconfig.h.in
index 0451855..eaee16f 100644
--- a/pyconfig.h.in
+++ b/pyconfig.h.in
@@ -574,6 +574,9 @@
/* Define to 1 if you have the <linux/tipc.h> header file. */
#undef HAVE_LINUX_TIPC_H
+/* Define to 1 if you have the <linux/random.h> header file. */
+#undef HAVE_LINUX_RANDOM_H
+
/* Define to 1 if you have the `lockf' function. */
#undef HAVE_LOCKF