2017-01-06 22:27:49 +00:00
|
|
|
diff --git a/Python/random.c b/Python/random.c
|
2017-05-11 12:57:29 +00:00
|
|
|
index d203939..4c27585 100644
|
2017-01-06 22:27:49 +00:00
|
|
|
--- a/Python/random.c
|
|
|
|
+++ b/Python/random.c
|
2017-05-11 12:57:29 +00:00
|
|
|
@@ -76,46 +76,7 @@ win32_urandom(unsigned char *buffer, Py_ssize_t size, int raise)
|
2017-01-06 21:17:13 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
-/* Issue #25003: Don't use getentropy() on Solaris (available since
|
|
|
|
- * Solaris 11.3), it is blocking whereas os.urandom() should not block. */
|
|
|
|
-#elif defined(HAVE_GETENTROPY) && !defined(sun)
|
|
|
|
-#define PY_GETENTROPY 1
|
|
|
|
-
|
|
|
|
-/* Fill buffer with size pseudo-random bytes generated by getentropy().
|
|
|
|
- Return 0 on success, or raise an exception and return -1 on error.
|
|
|
|
-
|
2017-01-06 22:27:49 +00:00
|
|
|
- If fatal is nonzero, call Py_FatalError() instead of raising an exception
|
|
|
|
- on error. */
|
2017-01-06 21:17:13 +00:00
|
|
|
-static int
|
2017-01-06 22:27:49 +00:00
|
|
|
-py_getentropy(unsigned char *buffer, Py_ssize_t size, int fatal)
|
2017-01-06 21:17:13 +00:00
|
|
|
-{
|
|
|
|
- while (size > 0) {
|
|
|
|
- Py_ssize_t len = Py_MIN(size, 256);
|
|
|
|
- int res;
|
2017-01-06 22:27:49 +00:00
|
|
|
-
|
|
|
|
- if (!fatal) {
|
2017-01-06 21:17:13 +00:00
|
|
|
- Py_BEGIN_ALLOW_THREADS
|
|
|
|
- res = getentropy(buffer, len);
|
|
|
|
- Py_END_ALLOW_THREADS
|
|
|
|
-
|
2017-01-06 22:27:49 +00:00
|
|
|
- if (res < 0) {
|
2017-01-06 21:17:13 +00:00
|
|
|
- PyErr_SetFromErrno(PyExc_OSError);
|
2017-01-06 22:27:49 +00:00
|
|
|
- return -1;
|
2017-01-06 21:17:13 +00:00
|
|
|
- }
|
2017-01-06 22:27:49 +00:00
|
|
|
- }
|
|
|
|
- else {
|
|
|
|
- res = getentropy(buffer, len);
|
|
|
|
- if (res < 0)
|
|
|
|
- Py_FatalError("getentropy() failed");
|
2017-01-06 21:17:13 +00:00
|
|
|
- }
|
|
|
|
-
|
|
|
|
- buffer += len;
|
|
|
|
- size -= len;
|
|
|
|
- }
|
|
|
|
- return 0;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-#else
|
2017-01-06 22:27:49 +00:00
|
|
|
+#else /* !MS_WINDOWS */
|
2017-01-06 21:17:13 +00:00
|
|
|
|
|
|
|
#if defined(HAVE_GETRANDOM) || defined(HAVE_GETRANDOM_SYSCALL)
|
|
|
|
#define PY_GETRANDOM 1
|
2017-05-11 12:57:29 +00:00
|
|
|
@@ -227,6 +188,59 @@ py_getrandom(void *buffer, Py_ssize_t size, int raise)
|
2017-01-06 21:17:13 +00:00
|
|
|
}
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
+
|
|
|
|
+/* Issue #25003: Don't use getentropy() on Solaris (available since
|
|
|
|
+ * Solaris 11.3), it is blocking whereas os.urandom() should not block. */
|
|
|
|
+#elif 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)
|
|
|
|
+{
|
|
|
|
+ /* Is getentropy() supported by the running kernel? Set to 0 if
|
|
|
|
+ getentropy() failed with ENOSYS. */
|
|
|
|
+ static int getentropy_works = 1;
|
|
|
|
+
|
|
|
|
+ if (!getentropy_works) {
|
|
|
|
+ return 0;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ 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) {
|
|
|
|
+ /* ENOSYS: the inner syscall is not supported by the running
|
|
|
|
+ kernel. */
|
|
|
|
+ if (errno == ENOSYS) {
|
|
|
|
+ getentropy_works = 0;
|
|
|
|
+ return 0;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (raise) {
|
|
|
|
+ PyErr_SetFromErrno(PyExc_OSError);
|
|
|
|
+ }
|
|
|
|
+ return -1;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ buffer += len;
|
|
|
|
+ size -= len;
|
|
|
|
+ }
|
|
|
|
+ return 1;
|
|
|
|
+}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
static struct {
|
2017-05-11 12:57:29 +00:00
|
|
|
@@ -288,7 +302,7 @@ dev_urandom_python(char *buffer, Py_ssize_t size)
|
2017-01-06 21:17:13 +00:00
|
|
|
int fd;
|
|
|
|
Py_ssize_t n;
|
2017-01-06 22:27:49 +00:00
|
|
|
struct _Py_stat_struct st;
|
2017-01-06 21:17:13 +00:00
|
|
|
-#ifdef PY_GETRANDOM
|
|
|
|
+#if defined(PY_GETRANDOM) || defined(PY_GETENTROPY)
|
|
|
|
int res;
|
|
|
|
#endif
|
|
|
|
|
2017-05-11 12:57:29 +00:00
|
|
|
@@ -297,6 +311,10 @@ dev_urandom_python(char *buffer, Py_ssize_t size)
|
2017-01-06 21:17:13 +00:00
|
|
|
|
|
|
|
#ifdef PY_GETRANDOM
|
2017-01-06 22:27:49 +00:00
|
|
|
res = py_getrandom(buffer, size, 1);
|
2017-01-06 21:17:13 +00:00
|
|
|
+#elif defined(PY_GETENTROPY)
|
2017-01-06 22:27:49 +00:00
|
|
|
+ res = py_getentropy(buffer, size, 1);
|
2017-01-06 21:17:13 +00:00
|
|
|
+#endif
|
|
|
|
+#if defined(PY_GETRANDOM) || defined(PY_GETENTROPY)
|
2017-05-11 12:57:29 +00:00
|
|
|
if (res < 0) {
|
2017-01-06 21:17:13 +00:00
|
|
|
return -1;
|
2017-05-11 12:57:29 +00:00
|
|
|
}
|
|
|
|
@@ -376,8 +394,8 @@ dev_urandom_close(void)
|
2017-01-06 21:17:13 +00:00
|
|
|
urandom_cache.fd = -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
+#endif /* !MS_WINDOWS */
|
|
|
|
|
|
|
|
-#endif
|
|
|
|
|
|
|
|
/* Fill buffer with pseudo-random bytes generated by a linear congruent
|
|
|
|
generator (LCG):
|
2017-05-11 12:57:29 +00:00
|
|
|
@@ -418,8 +436,6 @@ _PyOS_URandom(void *buffer, Py_ssize_t size)
|
2017-01-06 21:17:13 +00:00
|
|
|
|
|
|
|
#ifdef MS_WINDOWS
|
2017-01-06 22:27:49 +00:00
|
|
|
return win32_urandom((unsigned char *)buffer, size, 1);
|
2017-01-06 21:17:13 +00:00
|
|
|
-#elif defined(PY_GETENTROPY)
|
2017-01-06 22:27:49 +00:00
|
|
|
- return py_getentropy(buffer, size, 0);
|
2017-01-06 21:17:13 +00:00
|
|
|
#else
|
2017-01-06 22:27:49 +00:00
|
|
|
return dev_urandom_python((char*)buffer, size);
|
2017-01-06 21:17:13 +00:00
|
|
|
#endif
|
2017-05-11 12:57:29 +00:00
|
|
|
@@ -481,8 +497,6 @@ _PyRandom_Fini(void)
|
2017-01-06 21:17:13 +00:00
|
|
|
CryptReleaseContext(hCryptProv, 0);
|
|
|
|
hCryptProv = 0;
|
|
|
|
}
|
|
|
|
-#elif defined(PY_GETENTROPY)
|
|
|
|
- /* nothing to clean */
|
|
|
|
#else
|
|
|
|
dev_urandom_close();
|
|
|
|
#endif
|