diff options
Diffstat (limited to 'meta/recipes-devtools/python/python3/upstream-random-fixes.patch')
-rw-r--r-- | meta/recipes-devtools/python/python3/upstream-random-fixes.patch | 288 |
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 @@ | |||
1 | This patch updates random.c to match upstream python's code at revision | 1 | From 035ba5da3e53e45c712b39fe1f6fb743e697c032 Mon Sep 17 00:00:00 2001 |
2 | 8125d9a8152b. This addresses various issues around problems with glibc 2.24 | 2 | From: Victor Stinner <victor.stinner@gmail.com> |
3 | and 2.25 such that python would fail to start with: | 3 | Date: Mon, 9 Jan 2017 11:18:53 +0100 |
4 | 4 | Subject: [PATCH] Issue #29157: Prefer getrandom() over getentropy() | |
5 | [rpurdie@centos7 ~]$ /tmp/t2/sysroots/x86_64-pokysdk-linux/usr/bin/python3 | ||
6 | Fatal Python error: getentropy() failed | ||
7 | Aborted | ||
8 | |||
9 | (taken from our buildtools-tarball also breaks eSDK) | ||
10 | |||
11 | Upstream-Status: Backport | ||
12 | |||
13 | # HG changeset patch | ||
14 | # User Victor Stinner <victor.stinner@gmail.com> | ||
15 | # Date 1483957133 -3600 | ||
16 | # Node ID 8125d9a8152b79e712cb09c7094b9129b9bcea86 | ||
17 | # Parent 337461574c90281630751b6095c4e1baf380cf7d | ||
18 | Issue #29157: Prefer getrandom() over getentropy() | ||
19 | 5 | ||
20 | Copy and then adapt Python/random.c from default branch. Difference between 3.5 | 6 | Copy and then adapt Python/random.c from default branch. Difference between 3.5 |
21 | and default branches: | 7 | and default branches: |
@@ -26,12 +12,17 @@ and default branches: | |||
26 | * Python 3.5 has no _PyOS_URandomNonblock() function: _PyOS_URandom() | 12 | * Python 3.5 has no _PyOS_URandomNonblock() function: _PyOS_URandom() |
27 | works in non-blocking mode on Python 3.5 | 13 | works in non-blocking mode on Python 3.5 |
28 | 14 | ||
29 | RP 2017/1/22 | 15 | Upstream-Status: Backport [https://github.com/python/cpython/commit/035ba5da3e53e45c712b39fe1f6fb743e697c032] |
16 | Signed-off-by: Alexander Kanavin <alexander.kanavin@intel.com> | ||
17 | |||
18 | --- | ||
19 | Python/random.c | 494 +++++++++++++++++++++++++++++++++----------------------- | ||
20 | 1 file changed, 294 insertions(+), 200 deletions(-) | ||
30 | 21 | ||
31 | Index: Python-3.5.2/Python/random.c | 22 | diff --git a/Python/random.c b/Python/random.c |
32 | =================================================================== | 23 | index d203939..31f61d0 100644 |
33 | --- Python-3.5.2.orig/Python/random.c | 24 | --- a/Python/random.c |
34 | +++ Python-3.5.2/Python/random.c | 25 | +++ b/Python/random.c |
35 | @@ -1,6 +1,9 @@ | 26 | @@ -1,6 +1,9 @@ |
36 | #include "Python.h" | 27 | #include "Python.h" |
37 | #ifdef MS_WINDOWS | 28 | #ifdef MS_WINDOWS |
@@ -42,7 +33,7 @@ Index: Python-3.5.2/Python/random.c | |||
42 | #else | 33 | #else |
43 | # include <fcntl.h> | 34 | # include <fcntl.h> |
44 | # ifdef HAVE_SYS_STAT_H | 35 | # ifdef HAVE_SYS_STAT_H |
45 | @@ -36,10 +39,9 @@ win32_urandom_init(int raise) | 36 | @@ -37,10 +40,9 @@ win32_urandom_init(int raise) |
46 | return 0; | 37 | return 0; |
47 | 38 | ||
48 | error: | 39 | error: |
@@ -55,7 +46,7 @@ Index: Python-3.5.2/Python/random.c | |||
55 | return -1; | 46 | return -1; |
56 | } | 47 | } |
57 | 48 | ||
58 | @@ -52,8 +54,9 @@ win32_urandom(unsigned char *buffer, Py_ | 49 | @@ -53,8 +55,9 @@ win32_urandom(unsigned char *buffer, Py_ssize_t size, int raise) |
59 | 50 | ||
60 | if (hCryptProv == 0) | 51 | if (hCryptProv == 0) |
61 | { | 52 | { |
@@ -66,7 +57,7 @@ Index: Python-3.5.2/Python/random.c | |||
66 | } | 57 | } |
67 | 58 | ||
68 | while (size > 0) | 59 | while (size > 0) |
69 | @@ -62,11 +65,9 @@ win32_urandom(unsigned char *buffer, Py_ | 60 | @@ -63,11 +66,9 @@ win32_urandom(unsigned char *buffer, Py_ssize_t size, int raise) |
70 | if (!CryptGenRandom(hCryptProv, (DWORD)chunk, buffer)) | 61 | if (!CryptGenRandom(hCryptProv, (DWORD)chunk, buffer)) |
71 | { | 62 | { |
72 | /* CryptGenRandom() failed */ | 63 | /* CryptGenRandom() failed */ |
@@ -80,7 +71,7 @@ Index: Python-3.5.2/Python/random.c | |||
80 | return -1; | 71 | return -1; |
81 | } | 72 | } |
82 | buffer += chunk; | 73 | buffer += chunk; |
83 | @@ -75,55 +76,29 @@ win32_urandom(unsigned char *buffer, Py_ | 74 | @@ -76,58 +77,23 @@ win32_urandom(unsigned char *buffer, Py_ssize_t size, int raise) |
84 | return 0; | 75 | return 0; |
85 | } | 76 | } |
86 | 77 | ||
@@ -129,13 +120,19 @@ Index: Python-3.5.2/Python/random.c | |||
129 | #if defined(HAVE_GETRANDOM) || defined(HAVE_GETRANDOM_SYSCALL) | 120 | #if defined(HAVE_GETRANDOM) || defined(HAVE_GETRANDOM_SYSCALL) |
130 | #define PY_GETRANDOM 1 | 121 | #define PY_GETRANDOM 1 |
131 | 122 | ||
123 | -/* Call getrandom() | ||
132 | +/* Call getrandom() to get random bytes: | 124 | +/* Call getrandom() to get random bytes: |
133 | + | 125 | + |
134 | + - Return 1 on success | 126 | - Return 1 on success |
127 | - - Return 0 if getrandom() syscall is not available (failed with ENOSYS or | ||
128 | - EPERM) or if getrandom(GRND_NONBLOCK) failed with EAGAIN (system urandom | ||
129 | - not initialized yet) and raise=0. | ||
135 | + - Return 0 if getrandom() is not available (failed with ENOSYS or EPERM), | 130 | + - Return 0 if getrandom() is not available (failed with ENOSYS or EPERM), |
136 | + or if getrandom(GRND_NONBLOCK) failed with EAGAIN (system urandom not | 131 | + or if getrandom(GRND_NONBLOCK) failed with EAGAIN (system urandom not |
137 | + initialized yet). | 132 | + initialized yet). |
138 | + - Raise an exception (if raise is non-zero) and return -1 on error: | 133 | - Raise an exception (if raise is non-zero) and return -1 on error: |
134 | - getrandom() failed with EINTR and the Python signal handler raised an | ||
135 | - exception, or getrandom() failed with a different error. */ | ||
139 | + if getrandom() failed with EINTR, raise is non-zero and the Python signal | 136 | + if getrandom() failed with EINTR, raise is non-zero and the Python signal |
140 | + handler raised an exception, or if getrandom() failed with a different | 137 | + handler raised an exception, or if getrandom() failed with a different |
141 | + error. | 138 | + error. |
@@ -144,26 +141,16 @@ Index: Python-3.5.2/Python/random.c | |||
144 | static int | 141 | static int |
145 | py_getrandom(void *buffer, Py_ssize_t size, int raise) | 142 | py_getrandom(void *buffer, Py_ssize_t size, int raise) |
146 | { | 143 | { |
147 | - /* Is getrandom() supported by the running kernel? | 144 | @@ -142,16 +108,19 @@ py_getrandom(void *buffer, Py_ssize_t size, int raise) |
148 | - * Need Linux kernel 3.17 or newer, or Solaris 11.3 or newer */ | ||
149 | + /* Is getrandom() supported by the running kernel? Set to 0 if getrandom() | ||
150 | + failed with ENOSYS or EPERM. Need Linux kernel 3.17 or newer, or Solaris | ||
151 | + 11.3 or newer */ | ||
152 | static int getrandom_works = 1; | ||
153 | |||
154 | /* getrandom() on Linux will block if called before the kernel has | ||
155 | @@ -132,84 +107,165 @@ py_getrandom(void *buffer, Py_ssize_t si | ||
156 | * see https://bugs.python.org/issue26839. To avoid this, use the | 145 | * see https://bugs.python.org/issue26839. To avoid this, use the |
157 | * GRND_NONBLOCK flag. */ | 146 | * GRND_NONBLOCK flag. */ |
158 | const int flags = GRND_NONBLOCK; | 147 | const int flags = GRND_NONBLOCK; |
159 | - int n; | ||
160 | + char *dest; | 148 | + char *dest; |
161 | + long n; | 149 | long n; |
162 | 150 | ||
163 | - if (!getrandom_works) | 151 | if (!getrandom_works) { |
164 | + if (!getrandom_works) { | ||
165 | return 0; | 152 | return 0; |
166 | + } | 153 | } |
167 | 154 | ||
168 | + dest = buffer; | 155 | + dest = buffer; |
169 | while (0 < size) { | 156 | while (0 < size) { |
@@ -174,11 +161,8 @@ Index: Python-3.5.2/Python/random.c | |||
174 | + requested. */ | 161 | + requested. */ |
175 | n = Py_MIN(size, 1024); | 162 | n = Py_MIN(size, 1024); |
176 | #else | 163 | #else |
177 | - n = size; | 164 | n = Py_MIN(size, LONG_MAX); |
178 | + n = Py_MIN(size, LONG_MAX); | 165 | @@ -161,34 +130,35 @@ py_getrandom(void *buffer, Py_ssize_t size, int raise) |
179 | #endif | ||
180 | |||
181 | errno = 0; | ||
182 | #ifdef HAVE_GETRANDOM | 166 | #ifdef HAVE_GETRANDOM |
183 | if (raise) { | 167 | if (raise) { |
184 | Py_BEGIN_ALLOW_THREADS | 168 | Py_BEGIN_ALLOW_THREADS |
@@ -209,56 +193,45 @@ Index: Python-3.5.2/Python/random.c | |||
209 | #endif | 193 | #endif |
210 | 194 | ||
211 | if (n < 0) { | 195 | if (n < 0) { |
212 | - if (errno == ENOSYS) { | 196 | - /* ENOSYS: getrandom() syscall not supported by the kernel (but |
197 | - * maybe supported by the host which built Python). EPERM: | ||
198 | - * getrandom() syscall blocked by SECCOMP or something else. */ | ||
213 | + /* ENOSYS: the syscall is not supported by the kernel. | 199 | + /* ENOSYS: the syscall is not supported by the kernel. |
214 | + EPERM: the syscall is blocked by a security policy (ex: SECCOMP) | 200 | + EPERM: the syscall is blocked by a security policy (ex: SECCOMP) |
215 | + or something else. */ | 201 | + or something else. */ |
216 | + if (errno == ENOSYS || errno == EPERM) { | 202 | if (errno == ENOSYS || errno == EPERM) { |
217 | getrandom_works = 0; | 203 | getrandom_works = 0; |
218 | return 0; | 204 | return 0; |
219 | } | 205 | } |
220 | + | 206 | + |
221 | if (errno == EAGAIN) { | 207 | if (errno == EAGAIN) { |
222 | - /* If we failed with EAGAIN, the entropy pool was | 208 | /* getrandom(GRND_NONBLOCK) fails with EAGAIN if the system |
223 | - * uninitialized. In this case, we return failure to fall | 209 | urandom is not initialiazed yet. In this case, fall back on |
224 | - * back to reading from /dev/urandom. | 210 | @@ -202,169 +172,225 @@ py_getrandom(void *buffer, Py_ssize_t size, int raise) |
225 | - * | ||
226 | - * Note: In this case the data read will not be random so | ||
227 | - * should not be used for cryptographic purposes. Retaining | ||
228 | - * the existing semantics for practical purposes. */ | ||
229 | + /* getrandom(GRND_NONBLOCK) fails with EAGAIN if the system | ||
230 | + urandom is not initialiazed yet. In this case, fall back on | ||
231 | + reading from /dev/urandom. | ||
232 | + | ||
233 | + Note: In this case the data read will not be random so | ||
234 | + should not be used for cryptographic purposes. Retaining | ||
235 | + the existing semantics for practical purposes. */ | ||
236 | getrandom_works = 0; | ||
237 | return 0; | ||
238 | } | 211 | } |
239 | 212 | ||
240 | if (errno == EINTR) { | 213 | if (errno == EINTR) { |
241 | - if (PyErr_CheckSignals()) { | 214 | - if (PyErr_CheckSignals()) { |
242 | - if (!raise) | 215 | - if (!raise) { |
243 | - Py_FatalError("getrandom() interrupted by a signal"); | 216 | - Py_FatalError("getrandom() interrupted by a signal"); |
244 | - return -1; | ||
245 | + if (raise) { | 217 | + if (raise) { |
246 | + if (PyErr_CheckSignals()) { | 218 | + if (PyErr_CheckSignals()) { |
247 | + return -1; | 219 | + return -1; |
248 | + } | 220 | } |
221 | - return -1; | ||
249 | } | 222 | } |
223 | |||
250 | - /* retry getrandom() */ | 224 | - /* retry getrandom() */ |
251 | + | ||
252 | + /* retry getrandom() if it was interrupted by a signal */ | 225 | + /* retry getrandom() if it was interrupted by a signal */ |
253 | continue; | 226 | continue; |
254 | } | 227 | } |
255 | 228 | ||
256 | - if (raise) | 229 | if (raise) { |
257 | + if (raise) { | ||
258 | PyErr_SetFromErrno(PyExc_OSError); | 230 | PyErr_SetFromErrno(PyExc_OSError); |
259 | - else | 231 | } |
232 | - else { | ||
260 | - Py_FatalError("getrandom() failed"); | 233 | - Py_FatalError("getrandom() failed"); |
261 | + } | 234 | - } |
262 | return -1; | 235 | return -1; |
263 | } | 236 | } |
264 | 237 | ||
@@ -269,12 +242,19 @@ Index: Python-3.5.2/Python/random.c | |||
269 | return 1; | 242 | return 1; |
270 | } | 243 | } |
271 | -#endif | 244 | -#endif |
272 | + | 245 | |
246 | -static struct { | ||
247 | - int fd; | ||
248 | - dev_t st_dev; | ||
249 | - ino_t st_ino; | ||
250 | -} urandom_cache = { -1 }; | ||
273 | +#elif defined(HAVE_GETENTROPY) | 251 | +#elif defined(HAVE_GETENTROPY) |
274 | +#define PY_GETENTROPY 1 | 252 | +#define PY_GETENTROPY 1 |
275 | + | 253 | |
276 | +/* Fill buffer with size pseudo-random bytes generated by getentropy(): | 254 | +/* Fill buffer with size pseudo-random bytes generated by getentropy(): |
277 | + | 255 | |
256 | -/* Read 'size' random bytes from py_getrandom(). Fall back on reading from | ||
257 | - /dev/urandom if getrandom() is not available. | ||
278 | + - Return 1 on success | 258 | + - Return 1 on success |
279 | + - Return 0 if getentropy() syscall is not available (failed with ENOSYS or | 259 | + - Return 0 if getentropy() syscall is not available (failed with ENOSYS or |
280 | + EPERM). | 260 | + EPERM). |
@@ -282,25 +262,47 @@ Index: Python-3.5.2/Python/random.c | |||
282 | + if getentropy() failed with EINTR, raise is non-zero and the Python signal | 262 | + if getentropy() failed with EINTR, raise is non-zero and the Python signal |
283 | + handler raised an exception, or if getentropy() failed with a different | 263 | + handler raised an exception, or if getentropy() failed with a different |
284 | + error. | 264 | + error. |
285 | + | 265 | |
266 | - Call Py_FatalError() on error. */ | ||
267 | -static void | ||
268 | -dev_urandom_noraise(unsigned char *buffer, Py_ssize_t size) | ||
286 | + getentropy() is retried if it failed with EINTR: interrupted by a signal. */ | 269 | + getentropy() is retried if it failed with EINTR: interrupted by a signal. */ |
287 | +static int | 270 | +static int |
288 | +py_getentropy(char *buffer, Py_ssize_t size, int raise) | 271 | +py_getentropy(char *buffer, Py_ssize_t size, int raise) |
289 | +{ | 272 | { |
273 | - int fd; | ||
274 | - Py_ssize_t n; | ||
290 | + /* Is getentropy() supported by the running kernel? Set to 0 if | 275 | + /* Is getentropy() supported by the running kernel? Set to 0 if |
291 | + getentropy() failed with ENOSYS or EPERM. */ | 276 | + getentropy() failed with ENOSYS or EPERM. */ |
292 | + static int getentropy_works = 1; | 277 | + static int getentropy_works = 1; |
293 | + | 278 | |
279 | - assert (0 < size); | ||
280 | - | ||
281 | -#ifdef PY_GETRANDOM | ||
282 | - if (py_getrandom(buffer, size, 0) == 1) { | ||
283 | - return; | ||
294 | + if (!getentropy_works) { | 284 | + if (!getentropy_works) { |
295 | + return 0; | 285 | + return 0; |
296 | + } | 286 | } |
297 | + | 287 | - /* getrandom() failed with ENOSYS or EPERM, |
288 | - fall back on reading /dev/urandom */ | ||
289 | -#endif | ||
290 | |||
291 | - fd = _Py_open_noraise("/dev/urandom", O_RDONLY); | ||
292 | - if (fd < 0) { | ||
293 | - Py_FatalError("Failed to open /dev/urandom"); | ||
294 | - } | ||
298 | + while (size > 0) { | 295 | + while (size > 0) { |
299 | + /* getentropy() is limited to returning up to 256 bytes. Call it | 296 | + /* getentropy() is limited to returning up to 256 bytes. Call it |
300 | + multiple times if more bytes are requested. */ | 297 | + multiple times if more bytes are requested. */ |
301 | + Py_ssize_t len = Py_MIN(size, 256); | 298 | + Py_ssize_t len = Py_MIN(size, 256); |
302 | + int res; | 299 | + int res; |
303 | + | 300 | |
301 | - while (0 < size) | ||
302 | - { | ||
303 | - do { | ||
304 | - n = read(fd, buffer, (size_t)size); | ||
305 | - } while (n < 0 && errno == EINTR); | ||
304 | + if (raise) { | 306 | + if (raise) { |
305 | + Py_BEGIN_ALLOW_THREADS | 307 | + Py_BEGIN_ALLOW_THREADS |
306 | + res = getentropy(buffer, len); | 308 | + res = getentropy(buffer, len); |
@@ -309,7 +311,11 @@ Index: Python-3.5.2/Python/random.c | |||
309 | + else { | 311 | + else { |
310 | + res = getentropy(buffer, len); | 312 | + res = getentropy(buffer, len); |
311 | + } | 313 | + } |
312 | + | 314 | |
315 | - if (n <= 0) { | ||
316 | - /* read() failed or returned 0 bytes */ | ||
317 | - Py_FatalError("Failed to read bytes from /dev/urandom"); | ||
318 | - break; | ||
313 | + if (res < 0) { | 319 | + if (res < 0) { |
314 | + /* ENOSYS: the syscall is not supported by the running kernel. | 320 | + /* ENOSYS: the syscall is not supported by the running kernel. |
315 | + EPERM: the syscall is blocked by a security policy (ex: SECCOMP) | 321 | + EPERM: the syscall is blocked by a security policy (ex: SECCOMP) |
@@ -334,71 +340,44 @@ Index: Python-3.5.2/Python/random.c | |||
334 | + PyErr_SetFromErrno(PyExc_OSError); | 340 | + PyErr_SetFromErrno(PyExc_OSError); |
335 | + } | 341 | + } |
336 | + return -1; | 342 | + return -1; |
337 | + } | 343 | } |
344 | - buffer += n; | ||
345 | - size -= n; | ||
338 | + | 346 | + |
339 | + buffer += len; | 347 | + buffer += len; |
340 | + size -= len; | 348 | + size -= len; |
341 | + } | 349 | } |
350 | - close(fd); | ||
342 | + return 1; | 351 | + return 1; |
343 | +} | 352 | } |
344 | +#endif /* defined(HAVE_GETENTROPY) && !defined(sun) */ | 353 | +#endif /* defined(HAVE_GETENTROPY) && !defined(sun) */ |
345 | + | ||
346 | 354 | ||
347 | static struct { | 355 | -/* Read 'size' random bytes from py_getrandom(). Fall back on reading from |
348 | int fd; | 356 | - /dev/urandom if getrandom() is not available. |
349 | @@ -217,127 +273,123 @@ static struct { | ||
350 | ino_t st_ino; | ||
351 | } urandom_cache = { -1 }; | ||
352 | 357 | ||
358 | - Return 0 on success. Raise an exception and return -1 on error. */ | ||
359 | +static struct { | ||
360 | + int fd; | ||
361 | + dev_t st_dev; | ||
362 | + ino_t st_ino; | ||
363 | +} urandom_cache = { -1 }; | ||
364 | + | ||
353 | +/* Read random bytes from the /dev/urandom device: | 365 | +/* Read random bytes from the /dev/urandom device: |
354 | 366 | + | |
355 | -/* Read size bytes from /dev/urandom into buffer. | ||
356 | - Call Py_FatalError() on error. */ | ||
357 | -static void | ||
358 | -dev_urandom_noraise(unsigned char *buffer, Py_ssize_t size) | ||
359 | -{ | ||
360 | - int fd; | ||
361 | - Py_ssize_t n; | ||
362 | + - Return 0 on success | 367 | + - Return 0 on success |
363 | + - Raise an exception (if raise is non-zero) and return -1 on error | 368 | + - Raise an exception (if raise is non-zero) and return -1 on error |
364 | 369 | + | |
365 | - assert (0 < size); | ||
366 | + Possible causes of errors: | 370 | + Possible causes of errors: |
367 | 371 | + | |
368 | -#ifdef PY_GETRANDOM | ||
369 | - if (py_getrandom(buffer, size, 0) == 1) | ||
370 | - return; | ||
371 | - /* getrandom() is not supported by the running kernel, fall back | ||
372 | - * on reading /dev/urandom */ | ||
373 | -#endif | ||
374 | + - open() failed with ENOENT, ENXIO, ENODEV, EACCES: the /dev/urandom device | 372 | + - open() failed with ENOENT, ENXIO, ENODEV, EACCES: the /dev/urandom device |
375 | + was not found. For example, it was removed manually or not exposed in a | 373 | + was not found. For example, it was removed manually or not exposed in a |
376 | + chroot or container. | 374 | + chroot or container. |
377 | + - open() failed with a different error | 375 | + - open() failed with a different error |
378 | + - fstat() failed | 376 | + - fstat() failed |
379 | + - read() failed or returned 0 | 377 | + - read() failed or returned 0 |
380 | 378 | + | |
381 | - fd = _Py_open_noraise("/dev/urandom", O_RDONLY); | ||
382 | - if (fd < 0) | ||
383 | - Py_FatalError("Failed to open /dev/urandom"); | ||
384 | + read() is retried if it failed with EINTR: interrupted by a signal. | 379 | + read() is retried if it failed with EINTR: interrupted by a signal. |
385 | 380 | + | |
386 | - while (0 < size) | ||
387 | - { | ||
388 | - do { | ||
389 | - n = read(fd, buffer, (size_t)size); | ||
390 | - } while (n < 0 && errno == EINTR); | ||
391 | - if (n <= 0) | ||
392 | - { | ||
393 | - /* stop on error or if read(size) returned 0 */ | ||
394 | - Py_FatalError("Failed to read bytes from /dev/urandom"); | ||
395 | - break; | ||
396 | - } | ||
397 | - buffer += n; | ||
398 | - size -= (Py_ssize_t)n; | ||
399 | - } | ||
400 | - close(fd); | ||
401 | -} | ||
402 | + The file descriptor of the device is kept open between calls to avoid using | 381 | + The file descriptor of the device is kept open between calls to avoid using |
403 | + many file descriptors when run in parallel from multiple threads: | 382 | + many file descriptors when run in parallel from multiple threads: |
404 | + see the issue #18756. | 383 | + see the issue #18756. |
@@ -406,9 +385,7 @@ Index: Python-3.5.2/Python/random.c | |||
406 | + st_dev and st_ino fields of the file descriptor (from fstat()) are cached to | 385 | + st_dev and st_ino fields of the file descriptor (from fstat()) are cached to |
407 | + check if the file descriptor was replaced by a different file (which is | 386 | + check if the file descriptor was replaced by a different file (which is |
408 | + likely a bug in the application): see the issue #21207. | 387 | + likely a bug in the application): see the issue #21207. |
409 | 388 | + | |
410 | -/* Read size bytes from /dev/urandom into buffer. | ||
411 | - Return 0 on success, raise an exception and return -1 on error. */ | ||
412 | + If the file descriptor was closed or replaced, open a new file descriptor | 389 | + If the file descriptor was closed or replaced, open a new file descriptor |
413 | + but don't close the old file descriptor: it probably points to something | 390 | + but don't close the old file descriptor: it probably points to something |
414 | + important for some third-party code. */ | 391 | + important for some third-party code. */ |
@@ -422,22 +399,24 @@ Index: Python-3.5.2/Python/random.c | |||
422 | -#ifdef PY_GETRANDOM | 399 | -#ifdef PY_GETRANDOM |
423 | - int res; | 400 | - int res; |
424 | -#endif | 401 | -#endif |
425 | 402 | - | |
426 | - if (size <= 0) | 403 | - if (size <= 0) |
427 | - return 0; | 404 | - return 0; |
428 | + if (raise) { | ||
429 | + struct _Py_stat_struct st; | ||
430 | 405 | ||
431 | -#ifdef PY_GETRANDOM | 406 | -#ifdef PY_GETRANDOM |
432 | - res = py_getrandom(buffer, size, 1); | 407 | - res = py_getrandom(buffer, size, 1); |
433 | - if (res < 0) | 408 | - if (res < 0) { |
434 | - return -1; | 409 | - return -1; |
435 | - if (res == 1) | 410 | - } |
411 | - if (res == 1) { | ||
436 | - return 0; | 412 | - return 0; |
437 | - /* getrandom() is not supported by the running kernel, fall back | 413 | - } |
438 | - * on reading /dev/urandom */ | 414 | - /* getrandom() failed with ENOSYS or EPERM, |
415 | - fall back on reading /dev/urandom */ | ||
439 | -#endif | 416 | -#endif |
440 | - | 417 | + if (raise) { |
418 | + struct _Py_stat_struct st; | ||
419 | |||
441 | - if (urandom_cache.fd >= 0) { | 420 | - if (urandom_cache.fd >= 0) { |
442 | - /* Does the fd point to the same thing as before? (issue #21207) */ | 421 | - /* Does the fd point to the same thing as before? (issue #21207) */ |
443 | - if (_Py_fstat_noraise(urandom_cache.fd, &st) | 422 | - if (_Py_fstat_noraise(urandom_cache.fd, &st) |
@@ -516,8 +495,9 @@ Index: Python-3.5.2/Python/random.c | |||
516 | 495 | ||
517 | - do { | 496 | - do { |
518 | - n = _Py_read(fd, buffer, (size_t)size); | 497 | - n = _Py_read(fd, buffer, (size_t)size); |
519 | - if (n == -1) | 498 | - if (n == -1) { |
520 | - return -1; | 499 | - return -1; |
500 | - } | ||
521 | - if (n == 0) { | 501 | - if (n == 0) { |
522 | - PyErr_Format(PyExc_RuntimeError, | 502 | - PyErr_Format(PyExc_RuntimeError, |
523 | - "Failed to read %zi bytes from /dev/urandom", | 503 | - "Failed to read %zi bytes from /dev/urandom", |
@@ -566,7 +546,7 @@ Index: Python-3.5.2/Python/random.c | |||
566 | return 0; | 546 | return 0; |
567 | } | 547 | } |
568 | 548 | ||
569 | @@ -349,8 +401,8 @@ dev_urandom_close(void) | 549 | @@ -376,8 +402,8 @@ dev_urandom_close(void) |
570 | urandom_cache.fd = -1; | 550 | urandom_cache.fd = -1; |
571 | } | 551 | } |
572 | } | 552 | } |
@@ -576,7 +556,7 @@ Index: Python-3.5.2/Python/random.c | |||
576 | 556 | ||
577 | /* Fill buffer with pseudo-random bytes generated by a linear congruent | 557 | /* Fill buffer with pseudo-random bytes generated by a linear congruent |
578 | generator (LCG): | 558 | generator (LCG): |
579 | @@ -373,29 +425,98 @@ lcg_urandom(unsigned int x0, unsigned ch | 559 | @@ -400,31 +426,100 @@ lcg_urandom(unsigned int x0, unsigned char *buffer, size_t size) |
580 | } | 560 | } |
581 | } | 561 | } |
582 | 562 | ||
@@ -661,7 +641,7 @@ Index: Python-3.5.2/Python/random.c | |||
661 | #else | 641 | #else |
662 | - return dev_urandom_python((char*)buffer, size); | 642 | - return dev_urandom_python((char*)buffer, size); |
663 | + res = py_getentropy(buffer, size, raise); | 643 | + res = py_getentropy(buffer, size, raise); |
664 | #endif | 644 | +#endif |
665 | + if (res < 0) { | 645 | + if (res < 0) { |
666 | + return -1; | 646 | + return -1; |
667 | + } | 647 | + } |
@@ -673,9 +653,9 @@ Index: Python-3.5.2/Python/random.c | |||
673 | +#endif | 653 | +#endif |
674 | + | 654 | + |
675 | + return dev_urandom(buffer, size, raise); | 655 | + return dev_urandom(buffer, size, raise); |
676 | +#endif | 656 | #endif |
677 | +} | 657 | } |
678 | + | 658 | |
679 | +/* Fill buffer with size pseudo-random bytes from the operating system random | 659 | +/* Fill buffer with size pseudo-random bytes from the operating system random |
680 | + number generator (RNG). It is suitable for most cryptographic purposes | 660 | + number generator (RNG). It is suitable for most cryptographic purposes |
681 | + except long living private keys for asymmetric encryption. | 661 | + except long living private keys for asymmetric encryption. |
@@ -685,10 +665,12 @@ Index: Python-3.5.2/Python/random.c | |||
685 | +_PyOS_URandom(void *buffer, Py_ssize_t size) | 665 | +_PyOS_URandom(void *buffer, Py_ssize_t size) |
686 | +{ | 666 | +{ |
687 | + return pyurandom(buffer, size, 1); | 667 | + return pyurandom(buffer, size, 1); |
688 | } | 668 | +} |
689 | 669 | + | |
690 | void | 670 | void |
691 | @@ -436,13 +557,14 @@ _PyRandom_Init(void) | 671 | _PyRandom_Init(void) |
672 | { | ||
673 | @@ -463,13 +558,14 @@ _PyRandom_Init(void) | ||
692 | } | 674 | } |
693 | } | 675 | } |
694 | else { | 676 | else { |
@@ -710,7 +692,7 @@ Index: Python-3.5.2/Python/random.c | |||
710 | } | 692 | } |
711 | } | 693 | } |
712 | 694 | ||
713 | @@ -454,8 +576,6 @@ _PyRandom_Fini(void) | 695 | @@ -481,8 +577,6 @@ _PyRandom_Fini(void) |
714 | CryptReleaseContext(hCryptProv, 0); | 696 | CryptReleaseContext(hCryptProv, 0); |
715 | hCryptProv = 0; | 697 | hCryptProv = 0; |
716 | } | 698 | } |