[Python-checkins] cpython: Issue #29157: getrandom() is now preferred over getentropy()

victor.stinner python-checkins at python.org
Fri Jan 6 05:40:37 EST 2017


https://hg.python.org/cpython/rev/46ca697c6f26
changeset:   106017:46ca697c6f26
user:        Victor Stinner <victor.stinner at gmail.com>
date:        Fri Jan 06 11:26:01 2017 +0100
summary:
  Issue #29157: getrandom() is now preferred over getentropy()

The glibc now implements getentropy() on Linux using the getrandom() syscall.
But getentropy() doesn't support non-blocking mode.

Since getrandom() is tried first, it's not more needed to explicitly exclude
getentropy() on Solaris. Replace:

    if defined(HAVE_GETENTROPY) && !defined(sun)

with

    if defined(HAVE_GETENTROPY)

files:
  Python/random.c |  91 +++++++++++++++++++-----------------
  1 files changed, 47 insertions(+), 44 deletions(-)


diff --git a/Python/random.c b/Python/random.c
--- a/Python/random.c
+++ b/Python/random.c
@@ -79,45 +79,7 @@
 
 #else /* !MS_WINDOWS */
 
-/* Issue #25003: Don't use getentropy() on Solaris (available since
- * Solaris 11.3), it is blocking whereas os.urandom() should not block. */
-#if defined(HAVE_GETENTROPY) && !defined(sun)
-#define PY_GETENTROPY 1
-
-/* Fill buffer with size pseudo-random bytes generated by getentropy().
-   Return 1 on success, or raise an exception and return -1 on error.
-
-   If raise is zero, don't raise an exception on error. */
-static int
-py_getentropy(char *buffer, Py_ssize_t size, int raise)
-{
-    while (size > 0) {
-        Py_ssize_t len = Py_MIN(size, 256);
-        int res;
-
-        if (raise) {
-            Py_BEGIN_ALLOW_THREADS
-            res = getentropy(buffer, len);
-            Py_END_ALLOW_THREADS
-        }
-        else {
-            res = getentropy(buffer, len);
-        }
-
-        if (res < 0) {
-            if (raise) {
-                PyErr_SetFromErrno(PyExc_OSError);
-            }
-            return -1;
-        }
-
-        buffer += len;
-        size -= len;
-    }
-    return 1;
-}
-
-#elif defined(HAVE_GETRANDOM) || defined(HAVE_GETRANDOM_SYSCALL)
+#if defined(HAVE_GETRANDOM) || defined(HAVE_GETRANDOM_SYSCALL)
 #define PY_GETRANDOM 1
 
 /* Call getrandom()
@@ -217,7 +179,43 @@
     }
     return 1;
 }
-#endif /* defined(HAVE_GETRANDOM) || defined(HAVE_GETRANDOM_SYSCALL) */
+
+#elif defined(HAVE_GETENTROPY)
+#define PY_GETENTROPY 1
+
+/* Fill buffer with size pseudo-random bytes generated by getentropy().
+   Return 1 on success, or raise an exception and return -1 on error.
+
+   If raise is zero, don't raise an exception on error. */
+static int
+py_getentropy(char *buffer, Py_ssize_t size, int raise)
+{
+    while (size > 0) {
+        Py_ssize_t len = Py_MIN(size, 256);
+        int res;
+
+        if (raise) {
+            Py_BEGIN_ALLOW_THREADS
+            res = getentropy(buffer, len);
+            Py_END_ALLOW_THREADS
+        }
+        else {
+            res = getentropy(buffer, len);
+        }
+
+        if (res < 0) {
+            if (raise) {
+                PyErr_SetFromErrno(PyExc_OSError);
+            }
+            return -1;
+        }
+
+        buffer += len;
+        size -= len;
+    }
+    return 1;
+}
+#endif /* defined(HAVE_GETENTROPY) && !defined(sun) */
 
 
 static struct {
@@ -385,13 +383,18 @@
    Used sources of entropy ordered by preference, preferred source first:
 
    - CryptGenRandom() on Windows
+   - getrandom() function (ex: Linux and Solaris): call py_getrandom()
    - getentropy() function (ex: OpenBSD): call py_getentropy()
-   - getrandom() function (ex: Linux and Solaris): call py_getrandom()
    - /dev/urandom device
 
    Read from the /dev/urandom device if getrandom() or getentropy() function
    is not available or does not work.
 
+   Prefer getrandom() over getentropy() because getrandom() supports blocking
+   and non-blocking mode: see the PEP 524. Python requires non-blocking RNG at
+   startup to initialize its hash secret, but os.urandom() must block until the
+   system urandom is initialized (at least on Linux 3.17 and newer).
+
    Prefer getrandom() and getentropy() over reading directly /dev/urandom
    because these functions don't need file descriptors and so avoid ENFILE or
    EMFILE errors (too many open files): see the issue #18756.
@@ -439,10 +442,10 @@
 #else
 
 #if defined(PY_GETRANDOM) || defined(PY_GETENTROPY)
-#ifdef PY_GETENTROPY
+#ifdef PY_GETRANDOM
+    res = py_getrandom(buffer, size, blocking, raise);
+#else
     res = py_getentropy(buffer, size, raise);
-#else
-    res = py_getrandom(buffer, size, blocking, raise);
 #endif
     if (res < 0) {
         return -1;

-- 
Repository URL: https://hg.python.org/cpython


More information about the Python-checkins mailing list