|
6 | 6 | # ifdef HAVE_SYS_STAT_H |
7 | 7 | # include <sys/stat.h> |
8 | 8 | # endif |
| 9 | +# ifdef HAVE_LINUX_RANDOM_H |
| 10 | +# include <linux/random.h> |
| 11 | +# endif |
9 | 12 | # ifdef HAVE_GETRANDOM |
10 | 13 | # include <sys/random.h> |
11 | 14 | # elif defined(HAVE_GETRANDOM_SYSCALL) |
@@ -122,9 +125,13 @@ py_getrandom(void *buffer, Py_ssize_t size, int raise) |
122 | 125 | /* Is getrandom() supported by the running kernel? |
123 | 126 | * Need Linux kernel 3.17 or newer, or Solaris 11.3 or newer */ |
124 | 127 | static int getrandom_works = 1; |
125 | | - /* Use non-blocking /dev/urandom device. On Linux at boot, the getrandom() |
126 | | - * syscall blocks until /dev/urandom is initialized with enough entropy. */ |
127 | | - const int flags = 0; |
| 128 | + |
| 129 | + /* getrandom() on Linux will block if called before the kernel has |
| 130 | + * initialized the urandom entropy pool. This will cause Python |
| 131 | + * to hang on startup if called very early in the boot process - |
| 132 | + * see https://bugs.python.org/issue26839. To avoid this, use the |
| 133 | + * GRND_NONBLOCK flag. */ |
| 134 | + const int flags = GRND_NONBLOCK; |
128 | 135 | int n; |
129 | 136 |
|
130 | 137 | if (!getrandom_works) |
@@ -168,6 +175,17 @@ py_getrandom(void *buffer, Py_ssize_t size, int raise) |
168 | 175 | getrandom_works = 0; |
169 | 176 | return 0; |
170 | 177 | } |
| 178 | + if (errno == EAGAIN) { |
| 179 | + /* If we failed with EAGAIN, the entropy pool was |
| 180 | + * uninitialized. In this case, we return failure to fall |
| 181 | + * back to reading from /dev/urandom. |
| 182 | + * |
| 183 | + * Note: In this case the data read will not be random so |
| 184 | + * should not be used for cryptographic purposes. Retaining |
| 185 | + * the existing semantics for practical purposes. */ |
| 186 | + getrandom_works = 0; |
| 187 | + return 0; |
| 188 | + } |
171 | 189 |
|
172 | 190 | if (errno == EINTR) { |
173 | 191 | if (PyErr_CheckSignals()) { |
|
0 commit comments