churchyard / rpms / python3

Forked from rpms/python3 3 years ago
Clone

Blame 00250-getentropy.patch

6bb1189
diff -r ee1390c9b585 Python/random.c
6bb1189
--- a/Python/random.c	Wed Jan 04 12:02:30 2017 +0100
6bb1189
+++ b/Python/random.c	Wed Jan 04 18:32:21 2017 +0100
6bb1189
@@ -77,45 +77,8 @@ win32_urandom(unsigned char *buffer, Py_
6bb1189
     return 0;
6bb1189
 }
6bb1189
 
6bb1189
-/* Issue #25003: Don't use getentropy() on Solaris (available since
6bb1189
- * Solaris 11.3), it is blocking whereas os.urandom() should not block. */
6bb1189
-#elif defined(HAVE_GETENTROPY) && !defined(sun)
6bb1189
-#define PY_GETENTROPY 1
6bb1189
-
6bb1189
-/* Fill buffer with size pseudo-random bytes generated by getentropy().
6bb1189
-   Return 0 on success, or raise an exception and return -1 on error.
6bb1189
-
6bb1189
-   If raise is zero, don't raise an exception on error. */
6bb1189
-static int
6bb1189
-py_getentropy(char *buffer, Py_ssize_t size, int raise)
6bb1189
-{
6bb1189
-    while (size > 0) {
6bb1189
-        Py_ssize_t len = Py_MIN(size, 256);
6bb1189
-        int res;
6bb1189
+#else   /* !MS_WINDOWS */
6bb1189
 
6bb1189
-        if (raise) {
6bb1189
-            Py_BEGIN_ALLOW_THREADS
6bb1189
-            res = getentropy(buffer, len);
6bb1189
-            Py_END_ALLOW_THREADS
6bb1189
-        }
6bb1189
-        else {
6bb1189
-            res = getentropy(buffer, len);
6bb1189
-        }
6bb1189
-
6bb1189
-        if (res < 0) {
6bb1189
-            if (raise) {
6bb1189
-                PyErr_SetFromErrno(PyExc_OSError);
6bb1189
-            }
6bb1189
-            return -1;
6bb1189
-        }
6bb1189
-
6bb1189
-        buffer += len;
6bb1189
-        size -= len;
6bb1189
-    }
6bb1189
-    return 0;
6bb1189
-}
6bb1189
-
6bb1189
-#else
6bb1189
 
6bb1189
 #if defined(HAVE_GETRANDOM) || defined(HAVE_GETRANDOM_SYSCALL)
6bb1189
 #define PY_GETRANDOM 1
6bb1189
@@ -217,6 +180,59 @@ py_getrandom(void *buffer, Py_ssize_t si
6bb1189
     }
6bb1189
     return 1;
6bb1189
 }
6bb1189
+
6bb1189
+/* Issue #25003: Don't use getentropy() on Solaris (available since
6bb1189
+ * Solaris 11.3), it is blocking whereas os.urandom() should not block. */
6bb1189
+#elif defined(HAVE_GETENTROPY) && !defined(sun)
6bb1189
+#define PY_GETENTROPY 1
6bb1189
+
6bb1189
+/* Fill buffer with size pseudo-random bytes generated by getentropy().
6bb1189
+   Return 1 on success, or raise an exception and return -1 on error.
6bb1189
+
6bb1189
+   If raise is zero, don't raise an exception on error. */
6bb1189
+static int
6bb1189
+py_getentropy(char *buffer, Py_ssize_t size, int raise)
6bb1189
+{
6bb1189
+    /* Is getentropy() supported by the running kernel? Set to 0 if
6bb1189
+       getentropy() failed with ENOSYS. */
6bb1189
+    static int getentropy_works = 1;
6bb1189
+
6bb1189
+    if (!getentropy_works) {
6bb1189
+        return 0;
6bb1189
+    }
6bb1189
+
6bb1189
+    while (size > 0) {
6bb1189
+        Py_ssize_t len = Py_MIN(size, 256);
6bb1189
+        int res;
6bb1189
+
6bb1189
+        if (raise) {
6bb1189
+            Py_BEGIN_ALLOW_THREADS
6bb1189
+            res = getentropy(buffer, len);
6bb1189
+            Py_END_ALLOW_THREADS
6bb1189
+        }
6bb1189
+        else {
6bb1189
+            res = getentropy(buffer, len);
6bb1189
+        }
6bb1189
+
6bb1189
+        if (res < 0) {
6bb1189
+            /* ENOSYS: the inner syscall is not supported by the running
6bb1189
+               kernel. */
6bb1189
+            if (errno == ENOSYS) {
6bb1189
+                getentropy_works = 0;
6bb1189
+                return 0;
6bb1189
+            }
6bb1189
+
6bb1189
+            if (raise) {
6bb1189
+                PyErr_SetFromErrno(PyExc_OSError);
6bb1189
+            }
6bb1189
+            return -1;
6bb1189
+        }
6bb1189
+
6bb1189
+        buffer += len;
6bb1189
+        size -= len;
6bb1189
+    }
6bb1189
+    return 1;
6bb1189
+}
6bb1189
 #endif
6bb1189
 
6bb1189
 static struct {
6bb1189
@@ -236,7 +252,7 @@ dev_urandom(char *buffer, Py_ssize_t siz
6bb1189
 {
6bb1189
     int fd;
6bb1189
     Py_ssize_t n;
6bb1189
-#ifdef PY_GETRANDOM
6bb1189
+#if defined(PY_GETRANDOM) || defined(PY_GETENTROPY)
6bb1189
     int res;
6bb1189
 #endif
6bb1189
 
6bb1189
@@ -244,17 +260,20 @@ dev_urandom(char *buffer, Py_ssize_t siz
6bb1189
 
6bb1189
 #ifdef PY_GETRANDOM
6bb1189
     res = py_getrandom(buffer, size, blocking, raise);
6bb1189
+#elif defined(PY_GETENTROPY)
6bb1189
+    res = py_getentropy(buffer, size, raise);
6bb1189
+#endif
6bb1189
+#if defined(PY_GETRANDOM) || defined(PY_GETENTROPY)
6bb1189
     if (res < 0) {
6bb1189
         return -1;
6bb1189
     }
6bb1189
     if (res == 1) {
6bb1189
         return 0;
6bb1189
     }
6bb1189
-    /* getrandom() failed with ENOSYS or EPERM,
6bb1189
-       fall back on reading /dev/urandom */
6bb1189
+    /* function failed with ENOSYS or EPERM, fall back on reading
6bb1189
+       from /dev/urandom */
6bb1189
 #endif
6bb1189
 
6bb1189
-
6bb1189
     if (raise) {
6bb1189
         struct _Py_stat_struct st;
6bb1189
 
6bb1189
@@ -349,8 +368,8 @@ dev_urandom_close(void)
6bb1189
         urandom_cache.fd = -1;
6bb1189
     }
6bb1189
 }
6bb1189
+#endif   /* !MS_WINDOWS */
6bb1189
 
6bb1189
-#endif
6bb1189
 
6bb1189
 /* Fill buffer with pseudo-random bytes generated by a linear congruent
6bb1189
    generator (LCG):
6bb1189
@@ -395,8 +414,6 @@ pyurandom(void *buffer, Py_ssize_t size,
6bb1189
 
6bb1189
 #ifdef MS_WINDOWS
6bb1189
     return win32_urandom((unsigned char *)buffer, size, raise);
6bb1189
-#elif defined(PY_GETENTROPY)
6bb1189
-    return py_getentropy(buffer, size, raise);
6bb1189
 #else
6bb1189
     return dev_urandom(buffer, size, blocking, raise);
6bb1189
 #endif
6bb1189
@@ -491,8 +508,6 @@ void
6bb1189
         CryptReleaseContext(hCryptProv, 0);
6bb1189
         hCryptProv = 0;
6bb1189
     }
6bb1189
-#elif defined(PY_GETENTROPY)
6bb1189
-    /* nothing to clean */
6bb1189
 #else
6bb1189
     dev_urandom_close();
6bb1189
 #endif