aboutsummaryrefslogtreecommitdiffstats
path: root/meta/recipes-devtools/python/python3/upstream-random-fixes.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta/recipes-devtools/python/python3/upstream-random-fixes.patch')
-rw-r--r--meta/recipes-devtools/python/python3/upstream-random-fixes.patch288
1 files changed, 135 insertions, 153 deletions
diff --git a/meta/recipes-devtools/python/python3/upstream-random-fixes.patch b/meta/recipes-devtools/python/python3/upstream-random-fixes.patch
index 0d9152ccd7..9b40e8ac9f 100644
--- a/meta/recipes-devtools/python/python3/upstream-random-fixes.patch
+++ b/meta/recipes-devtools/python/python3/upstream-random-fixes.patch
@@ -1,21 +1,7 @@
-This patch updates random.c to match upstream python's code at revision
-8125d9a8152b. This addresses various issues around problems with glibc 2.24
-and 2.25 such that python would fail to start with:
-
-[rpurdie@centos7 ~]$ /tmp/t2/sysroots/x86_64-pokysdk-linux/usr/bin/python3
-Fatal Python error: getentropy() failed
-Aborted
-
-(taken from our buildtools-tarball also breaks eSDK)
-
-Upstream-Status: Backport
-
-# HG changeset patch
-# User Victor Stinner <victor.stinner@gmail.com>
-# Date 1483957133 -3600
-# Node ID 8125d9a8152b79e712cb09c7094b9129b9bcea86
-# Parent 337461574c90281630751b6095c4e1baf380cf7d
-Issue #29157: Prefer getrandom() over getentropy()
+From 035ba5da3e53e45c712b39fe1f6fb743e697c032 Mon Sep 17 00:00:00 2001
+From: Victor Stinner <victor.stinner@gmail.com>
+Date: Mon, 9 Jan 2017 11:18:53 +0100
+Subject: [PATCH] Issue #29157: Prefer getrandom() over getentropy()
Copy and then adapt Python/random.c from default branch. Difference between 3.5
and default branches:
@@ -26,12 +12,17 @@ and default branches:
* Python 3.5 has no _PyOS_URandomNonblock() function: _PyOS_URandom()
works in non-blocking mode on Python 3.5
-RP 2017/1/22
+Upstream-Status: Backport [https://github.com/python/cpython/commit/035ba5da3e53e45c712b39fe1f6fb743e697c032]
+Signed-off-by: Alexander Kanavin <alexander.kanavin@intel.com>
+
+---
+ Python/random.c | 494 +++++++++++++++++++++++++++++++++-----------------------
+ 1 file changed, 294 insertions(+), 200 deletions(-)
-Index: Python-3.5.2/Python/random.c
-===================================================================
---- Python-3.5.2.orig/Python/random.c
-+++ Python-3.5.2/Python/random.c
+diff --git a/Python/random.c b/Python/random.c
+index d203939..31f61d0 100644
+--- a/Python/random.c
++++ b/Python/random.c
@@ -1,6 +1,9 @@
#include "Python.h"
#ifdef MS_WINDOWS
@@ -42,7 +33,7 @@ Index: Python-3.5.2/Python/random.c
#else
# include <fcntl.h>
# ifdef HAVE_SYS_STAT_H
-@@ -36,10 +39,9 @@ win32_urandom_init(int raise)
+@@ -37,10 +40,9 @@ win32_urandom_init(int raise)
return 0;
error:
@@ -55,7 +46,7 @@ Index: Python-3.5.2/Python/random.c
return -1;
}
-@@ -52,8 +54,9 @@ win32_urandom(unsigned char *buffer, Py_
+@@ -53,8 +55,9 @@ win32_urandom(unsigned char *buffer, Py_ssize_t size, int raise)
if (hCryptProv == 0)
{
@@ -66,7 +57,7 @@ Index: Python-3.5.2/Python/random.c
}
while (size > 0)
-@@ -62,11 +65,9 @@ win32_urandom(unsigned char *buffer, Py_
+@@ -63,11 +66,9 @@ win32_urandom(unsigned char *buffer, Py_ssize_t size, int raise)
if (!CryptGenRandom(hCryptProv, (DWORD)chunk, buffer))
{
/* CryptGenRandom() failed */
@@ -80,7 +71,7 @@ Index: Python-3.5.2/Python/random.c
return -1;
}
buffer += chunk;
-@@ -75,55 +76,29 @@ win32_urandom(unsigned char *buffer, Py_
+@@ -76,58 +77,23 @@ win32_urandom(unsigned char *buffer, Py_ssize_t size, int raise)
return 0;
}
@@ -129,13 +120,19 @@ Index: Python-3.5.2/Python/random.c
#if defined(HAVE_GETRANDOM) || defined(HAVE_GETRANDOM_SYSCALL)
#define PY_GETRANDOM 1
+-/* Call getrandom()
+/* Call getrandom() to get random bytes:
+
-+ - Return 1 on success
+ - Return 1 on success
+- - Return 0 if getrandom() syscall is not available (failed with ENOSYS or
+- EPERM) or if getrandom(GRND_NONBLOCK) failed with EAGAIN (system urandom
+- not initialized yet) and raise=0.
+ - Return 0 if getrandom() is not available (failed with ENOSYS or EPERM),
+ or if getrandom(GRND_NONBLOCK) failed with EAGAIN (system urandom not
+ initialized yet).
-+ - Raise an exception (if raise is non-zero) and return -1 on error:
+ - Raise an exception (if raise is non-zero) and return -1 on error:
+- getrandom() failed with EINTR and the Python signal handler raised an
+- exception, or getrandom() failed with a different error. */
+ if getrandom() failed with EINTR, raise is non-zero and the Python signal
+ handler raised an exception, or if getrandom() failed with a different
+ error.
@@ -144,26 +141,16 @@ Index: Python-3.5.2/Python/random.c
static int
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 */
-+ /* Is getrandom() supported by the running kernel? Set to 0 if getrandom()
-+ failed with ENOSYS or EPERM. Need Linux kernel 3.17 or newer, or Solaris
-+ 11.3 or newer */
- static int getrandom_works = 1;
-
- /* getrandom() on Linux will block if called before the kernel has
-@@ -132,84 +107,165 @@ py_getrandom(void *buffer, Py_ssize_t si
+@@ -142,16 +108,19 @@ py_getrandom(void *buffer, Py_ssize_t size, int raise)
* see https://bugs.python.org/issue26839. To avoid this, use the
* GRND_NONBLOCK flag. */
const int flags = GRND_NONBLOCK;
-- int n;
+ char *dest;
-+ long n;
+ long n;
-- if (!getrandom_works)
-+ if (!getrandom_works) {
+ if (!getrandom_works) {
return 0;
-+ }
+ }
+ dest = buffer;
while (0 < size) {
@@ -174,11 +161,8 @@ Index: Python-3.5.2/Python/random.c
+ requested. */
n = Py_MIN(size, 1024);
#else
-- n = size;
-+ n = Py_MIN(size, LONG_MAX);
- #endif
-
- errno = 0;
+ n = Py_MIN(size, LONG_MAX);
+@@ -161,34 +130,35 @@ py_getrandom(void *buffer, Py_ssize_t size, int raise)
#ifdef HAVE_GETRANDOM
if (raise) {
Py_BEGIN_ALLOW_THREADS
@@ -209,56 +193,45 @@ Index: Python-3.5.2/Python/random.c
#endif
if (n < 0) {
-- if (errno == ENOSYS) {
+- /* ENOSYS: getrandom() syscall not supported by the kernel (but
+- * maybe supported by the host which built Python). EPERM:
+- * getrandom() syscall blocked by SECCOMP or something else. */
+ /* ENOSYS: the syscall is not supported by the kernel.
+ EPERM: the syscall is blocked by a security policy (ex: SECCOMP)
+ or something else. */
-+ if (errno == ENOSYS || errno == EPERM) {
+ if (errno == ENOSYS || errno == EPERM) {
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(GRND_NONBLOCK) fails with EAGAIN if the system
-+ urandom is not initialiazed yet. In this case, fall back on
-+ 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;
+ /* getrandom(GRND_NONBLOCK) fails with EAGAIN if the system
+ urandom is not initialiazed yet. In this case, fall back on
+@@ -202,169 +172,225 @@ py_getrandom(void *buffer, Py_ssize_t size, int raise)
}
if (errno == EINTR) {
- if (PyErr_CheckSignals()) {
-- if (!raise)
+- if (!raise) {
- Py_FatalError("getrandom() interrupted by a signal");
-- return -1;
+ if (raise) {
+ if (PyErr_CheckSignals()) {
+ return -1;
-+ }
+ }
+- return -1;
}
+
- /* retry getrandom() */
-+
+ /* retry getrandom() if it was interrupted by a signal */
continue;
}
-- if (raise)
-+ if (raise) {
+ if (raise) {
PyErr_SetFromErrno(PyExc_OSError);
-- else
+ }
+- else {
- Py_FatalError("getrandom() failed");
-+ }
+- }
return -1;
}
@@ -269,12 +242,19 @@ Index: Python-3.5.2/Python/random.c
return 1;
}
-#endif
-+
+
+-static struct {
+- int fd;
+- dev_t st_dev;
+- ino_t st_ino;
+-} urandom_cache = { -1 };
+#elif defined(HAVE_GETENTROPY)
+#define PY_GETENTROPY 1
-+
+
+/* Fill buffer with size pseudo-random bytes generated by getentropy():
-+
+
+-/* Read 'size' random bytes from py_getrandom(). Fall back on reading from
+- /dev/urandom if getrandom() is not available.
+ - Return 1 on success
+ - Return 0 if getentropy() syscall is not available (failed with ENOSYS or
+ EPERM).
@@ -282,25 +262,47 @@ Index: Python-3.5.2/Python/random.c
+ if getentropy() failed with EINTR, raise is non-zero and the Python signal
+ handler raised an exception, or if getentropy() failed with a different
+ error.
-+
+
+- Call Py_FatalError() on error. */
+-static void
+-dev_urandom_noraise(unsigned char *buffer, Py_ssize_t size)
+ getentropy() is retried if it failed with EINTR: interrupted by a signal. */
+static int
+py_getentropy(char *buffer, Py_ssize_t size, int raise)
-+{
+ {
+- int fd;
+- Py_ssize_t n;
+ /* Is getentropy() supported by the running kernel? Set to 0 if
+ getentropy() failed with ENOSYS or EPERM. */
+ static int getentropy_works = 1;
-+
+
+- assert (0 < size);
+-
+-#ifdef PY_GETRANDOM
+- if (py_getrandom(buffer, size, 0) == 1) {
+- return;
+ if (!getentropy_works) {
+ return 0;
-+ }
-+
+ }
+- /* getrandom() failed with ENOSYS or EPERM,
+- fall back on reading /dev/urandom */
+-#endif
+
+- fd = _Py_open_noraise("/dev/urandom", O_RDONLY);
+- if (fd < 0) {
+- Py_FatalError("Failed to open /dev/urandom");
+- }
+ while (size > 0) {
+ /* getentropy() is limited to returning up to 256 bytes. Call it
+ multiple times if more bytes are requested. */
+ Py_ssize_t len = Py_MIN(size, 256);
+ int res;
-+
+
+- while (0 < size)
+- {
+- do {
+- n = read(fd, buffer, (size_t)size);
+- } while (n < 0 && errno == EINTR);
+ if (raise) {
+ Py_BEGIN_ALLOW_THREADS
+ res = getentropy(buffer, len);
@@ -309,7 +311,11 @@ Index: Python-3.5.2/Python/random.c
+ else {
+ res = getentropy(buffer, len);
+ }
-+
+
+- if (n <= 0) {
+- /* read() failed or returned 0 bytes */
+- Py_FatalError("Failed to read bytes from /dev/urandom");
+- break;
+ if (res < 0) {
+ /* ENOSYS: the syscall is not supported by the running kernel.
+ EPERM: the syscall is blocked by a security policy (ex: SECCOMP)
@@ -334,71 +340,44 @@ Index: Python-3.5.2/Python/random.c
+ PyErr_SetFromErrno(PyExc_OSError);
+ }
+ return -1;
-+ }
+ }
+- buffer += n;
+- size -= n;
+
+ buffer += len;
+ size -= len;
-+ }
+ }
+- close(fd);
+ return 1;
-+}
+ }
+#endif /* defined(HAVE_GETENTROPY) && !defined(sun) */
-+
- static struct {
- int fd;
-@@ -217,127 +273,123 @@ static struct {
- ino_t st_ino;
- } urandom_cache = { -1 };
+-/* Read 'size' random bytes from py_getrandom(). Fall back on reading from
+- /dev/urandom if getrandom() is not available.
+- Return 0 on success. Raise an exception and return -1 on error. */
++static struct {
++ int fd;
++ dev_t st_dev;
++ ino_t st_ino;
++} urandom_cache = { -1 };
++
+/* Read random bytes from the /dev/urandom device:
-
--/* Read size bytes from /dev/urandom into buffer.
-- Call Py_FatalError() on error. */
--static void
--dev_urandom_noraise(unsigned char *buffer, Py_ssize_t size)
--{
-- int fd;
-- Py_ssize_t n;
++
+ - Return 0 on success
+ - Raise an exception (if raise is non-zero) and return -1 on error
-
-- assert (0 < size);
++
+ Possible causes of errors:
-
--#ifdef PY_GETRANDOM
-- if (py_getrandom(buffer, size, 0) == 1)
-- return;
-- /* getrandom() is not supported by the running kernel, fall back
-- * on reading /dev/urandom */
--#endif
++
+ - open() failed with ENOENT, ENXIO, ENODEV, EACCES: the /dev/urandom device
+ was not found. For example, it was removed manually or not exposed in a
+ chroot or container.
+ - open() failed with a different error
+ - fstat() failed
+ - read() failed or returned 0
-
-- fd = _Py_open_noraise("/dev/urandom", O_RDONLY);
-- if (fd < 0)
-- Py_FatalError("Failed to open /dev/urandom");
++
+ read() is retried if it failed with EINTR: interrupted by a signal.
-
-- while (0 < size)
-- {
-- do {
-- n = read(fd, buffer, (size_t)size);
-- } while (n < 0 && errno == EINTR);
-- if (n <= 0)
-- {
-- /* stop on error or if read(size) returned 0 */
-- Py_FatalError("Failed to read bytes from /dev/urandom");
-- break;
-- }
-- buffer += n;
-- size -= (Py_ssize_t)n;
-- }
-- close(fd);
--}
++
+ The file descriptor of the device is kept open between calls to avoid using
+ many file descriptors when run in parallel from multiple threads:
+ see the issue #18756.
@@ -406,9 +385,7 @@ Index: Python-3.5.2/Python/random.c
+ st_dev and st_ino fields of the file descriptor (from fstat()) are cached to
+ check if the file descriptor was replaced by a different file (which is
+ likely a bug in the application): see the issue #21207.
-
--/* Read size bytes from /dev/urandom into buffer.
-- Return 0 on success, raise an exception and return -1 on error. */
++
+ If the file descriptor was closed or replaced, open a new file descriptor
+ but don't close the old file descriptor: it probably points to something
+ important for some third-party code. */
@@ -422,22 +399,24 @@ Index: Python-3.5.2/Python/random.c
-#ifdef PY_GETRANDOM
- int res;
-#endif
-
+-
- if (size <= 0)
- return 0;
-+ if (raise) {
-+ struct _Py_stat_struct st;
-#ifdef PY_GETRANDOM
- res = py_getrandom(buffer, size, 1);
-- if (res < 0)
+- if (res < 0) {
- return -1;
-- if (res == 1)
+- }
+- if (res == 1) {
- return 0;
-- /* getrandom() is not supported by the running kernel, fall back
-- * on reading /dev/urandom */
+- }
+- /* getrandom() failed with ENOSYS or EPERM,
+- fall back on reading /dev/urandom */
-#endif
--
++ if (raise) {
++ struct _Py_stat_struct st;
+
- if (urandom_cache.fd >= 0) {
- /* Does the fd point to the same thing as before? (issue #21207) */
- if (_Py_fstat_noraise(urandom_cache.fd, &st)
@@ -516,8 +495,9 @@ Index: Python-3.5.2/Python/random.c
- do {
- n = _Py_read(fd, buffer, (size_t)size);
-- if (n == -1)
+- if (n == -1) {
- return -1;
+- }
- if (n == 0) {
- PyErr_Format(PyExc_RuntimeError,
- "Failed to read %zi bytes from /dev/urandom",
@@ -566,7 +546,7 @@ Index: Python-3.5.2/Python/random.c
return 0;
}
-@@ -349,8 +401,8 @@ dev_urandom_close(void)
+@@ -376,8 +402,8 @@ dev_urandom_close(void)
urandom_cache.fd = -1;
}
}
@@ -576,7 +556,7 @@ Index: Python-3.5.2/Python/random.c
/* Fill buffer with pseudo-random bytes generated by a linear congruent
generator (LCG):
-@@ -373,29 +425,98 @@ lcg_urandom(unsigned int x0, unsigned ch
+@@ -400,31 +426,100 @@ lcg_urandom(unsigned int x0, unsigned char *buffer, size_t size)
}
}
@@ -661,7 +641,7 @@ Index: Python-3.5.2/Python/random.c
#else
- return dev_urandom_python((char*)buffer, size);
+ res = py_getentropy(buffer, size, raise);
- #endif
++#endif
+ if (res < 0) {
+ return -1;
+ }
@@ -673,9 +653,9 @@ Index: Python-3.5.2/Python/random.c
+#endif
+
+ return dev_urandom(buffer, size, raise);
-+#endif
-+}
-+
+ #endif
+ }
+
+/* Fill buffer with size pseudo-random bytes from the operating system random
+ number generator (RNG). It is suitable for most cryptographic purposes
+ except long living private keys for asymmetric encryption.
@@ -685,10 +665,12 @@ Index: Python-3.5.2/Python/random.c
+_PyOS_URandom(void *buffer, Py_ssize_t size)
+{
+ return pyurandom(buffer, size, 1);
- }
-
++}
++
void
-@@ -436,13 +557,14 @@ _PyRandom_Init(void)
+ _PyRandom_Init(void)
+ {
+@@ -463,13 +558,14 @@ _PyRandom_Init(void)
}
}
else {
@@ -710,7 +692,7 @@ Index: Python-3.5.2/Python/random.c
}
}
-@@ -454,8 +576,6 @@ _PyRandom_Fini(void)
+@@ -481,8 +577,6 @@ _PyRandom_Fini(void)
CryptReleaseContext(hCryptProv, 0);
hCryptProv = 0;
}