@@ -119,11 +119,20 @@ py_getentropy(unsigned char *buffer, Py_ssize_t size, int fatal)
119119#if defined(HAVE_GETRANDOM ) || defined(HAVE_GETRANDOM_SYSCALL )
120120#define PY_GETRANDOM 1
121121
122+ /* Call getrandom()
123+ - Return 1 on success
124+ - Return 0 if getrandom() syscall is not available (failed with ENOSYS)
125+ or if getrandom(GRND_NONBLOCK) failed with EAGAIN (system urandom
126+ not initialized yet) and raise=0.
127+ - Raise an exception (if raise is non-zero) and return -1 on error:
128+ getrandom() failed with EINTR and the Python signal handler raised an
129+ exception, or getrandom() failed with a different error. */
122130static int
123131py_getrandom (void * buffer , Py_ssize_t size , int raise )
124132{
125- /* Is getrandom() supported by the running kernel?
126- * Need Linux kernel 3.17 or newer, or Solaris 11.3 or newer */
133+ /* Is getrandom() supported by the running kernel? Set to 0 if getrandom()
134+ failed with ENOSYS. Need Linux kernel 3.17 or newer, or Solaris
135+ 11.3 or newer */
127136 static int getrandom_works = 1 ;
128137
129138 /* getrandom() on Linux will block if called before the kernel has
@@ -134,8 +143,9 @@ py_getrandom(void *buffer, Py_ssize_t size, int raise)
134143 const int flags = GRND_NONBLOCK ;
135144 long n ;
136145
137- if (!getrandom_works )
146+ if (!getrandom_works ) {
138147 return 0 ;
148+ }
139149
140150 while (0 < size ) {
141151#ifdef sun
@@ -171,36 +181,42 @@ py_getrandom(void *buffer, Py_ssize_t size, int raise)
171181#endif
172182
173183 if (n < 0 ) {
184+ /* ENOSYS: getrandom() syscall not supported by the kernel (but
185+ * maybe supported by the host which built Python). */
174186 if (errno == ENOSYS ) {
175187 getrandom_works = 0 ;
176188 return 0 ;
177189 }
178190 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. */
191+ /* getrandom(GRND_NONBLOCK) fails with EAGAIN if the system
192+ urandom is not initialiazed yet . In this case, fall back on
193+ reading from /dev/urandom.
194+
195+ Note: In this case the data read will not be random so
196+ should not be used for cryptographic purposes. Retaining
197+ the existing semantics for practical purposes. */
186198 getrandom_works = 0 ;
187199 return 0 ;
188200 }
189201
190202 if (errno == EINTR ) {
191203 if (PyErr_CheckSignals ()) {
192- if (!raise )
204+ if (!raise ) {
193205 Py_FatalError ("getrandom() interrupted by a signal" );
206+ }
194207 return -1 ;
195208 }
209+
196210 /* retry getrandom() */
197211 continue ;
198212 }
199213
200- if (raise )
214+ if (raise ) {
201215 PyErr_SetFromErrno (PyExc_OSError );
202- else
216+ }
217+ else {
203218 Py_FatalError ("getrandom() failed" );
219+ }
204220 return -1 ;
205221 }
206222
@@ -218,7 +234,9 @@ static struct {
218234} urandom_cache = { -1 };
219235
220236
221- /* Read size bytes from /dev/urandom into buffer.
237+ /* Read 'size' random bytes from py_getrandom(). Fall back on reading from
238+ /dev/urandom if getrandom() is not available.
239+
222240 Call Py_FatalError() on error. */
223241static void
224242dev_urandom_noraise (unsigned char * buffer , Py_ssize_t size )
@@ -229,24 +247,26 @@ dev_urandom_noraise(unsigned char *buffer, Py_ssize_t size)
229247 assert (0 < size );
230248
231249#ifdef PY_GETRANDOM
232- if (py_getrandom (buffer , size , 0 ) == 1 )
250+ if (py_getrandom (buffer , size , 0 ) == 1 ) {
233251 return ;
234- /* getrandom() is not supported by the running kernel, fall back
235- * on reading /dev/urandom */
252+ }
253+ /* getrandom() failed with ENOSYS,
254+ fall back on reading /dev/urandom */
236255#endif
237256
238257 fd = _Py_open_noraise ("/dev/urandom" , O_RDONLY );
239- if (fd < 0 )
258+ if (fd < 0 ) {
240259 Py_FatalError ("Failed to open /dev/urandom" );
260+ }
241261
242262 while (0 < size )
243263 {
244264 do {
245265 n = read (fd , buffer , (size_t )size );
246266 } while (n < 0 && errno == EINTR );
247- if ( n <= 0 )
248- {
249- /* stop on error or if read(size) returned 0 */
267+
268+ if ( n <= 0 ) {
269+ /* read() failed or returned 0 bytes */
250270 Py_FatalError ("Failed to read bytes from /dev/urandom" );
251271 break ;
252272 }
@@ -256,8 +276,10 @@ dev_urandom_noraise(unsigned char *buffer, Py_ssize_t size)
256276 close (fd );
257277}
258278
259- /* Read size bytes from /dev/urandom into buffer.
260- Return 0 on success, raise an exception and return -1 on error. */
279+ /* Read 'size' random bytes from py_getrandom(). Fall back on reading from
280+ /dev/urandom if getrandom() is not available.
281+
282+ Return 0 on success. Raise an exception and return -1 on error. */
261283static int
262284dev_urandom_python (char * buffer , Py_ssize_t size )
263285{
@@ -273,12 +295,14 @@ dev_urandom_python(char *buffer, Py_ssize_t size)
273295
274296#ifdef PY_GETRANDOM
275297 res = py_getrandom (buffer , size , 1 );
276- if (res < 0 )
298+ if (res < 0 ) {
277299 return -1 ;
278- if (res == 1 )
300+ }
301+ if (res == 1 ) {
279302 return 0 ;
280- /* getrandom() is not supported by the running kernel, fall back
281- * on reading /dev/urandom */
303+ }
304+ /* getrandom() failed with ENOSYS,
305+ fall back on reading /dev/urandom */
282306#endif
283307
284308 if (urandom_cache .fd >= 0 ) {
@@ -325,8 +349,9 @@ dev_urandom_python(char *buffer, Py_ssize_t size)
325349
326350 do {
327351 n = _Py_read (fd , buffer , (size_t )size );
328- if (n == -1 )
352+ if (n == -1 ) {
329353 return -1 ;
354+ }
330355 if (n == 0 ) {
331356 PyErr_Format (PyExc_RuntimeError ,
332357 "Failed to read %zi bytes from /dev/urandom" ,
0 commit comments