Issue #29157: getrandom() is now preferred over getentropy()
The glibc now implements getentropy() on Linux using the getrandom() syscall. But getentropy() doesn't support non-blocking mode. Since getrandom() is tried first, it's not more needed to explicitly exclude getentropy() on Solaris. Replace: if defined(HAVE_GETENTROPY) && !defined(sun) with if defined(HAVE_GETENTROPY)
This commit is contained in:
parent
a49a2078e8
commit
2f7964393d
|
@ -79,45 +79,7 @@ win32_urandom(unsigned char *buffer, Py_ssize_t size, int raise)
|
|||
|
||||
#else /* !MS_WINDOWS */
|
||||
|
||||
/* Issue #25003: Don't use getentropy() on Solaris (available since
|
||||
* Solaris 11.3), it is blocking whereas os.urandom() should not block. */
|
||||
#if 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)
|
||||
{
|
||||
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) {
|
||||
if (raise) {
|
||||
PyErr_SetFromErrno(PyExc_OSError);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
buffer += len;
|
||||
size -= len;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
#elif defined(HAVE_GETRANDOM) || defined(HAVE_GETRANDOM_SYSCALL)
|
||||
#if defined(HAVE_GETRANDOM) || defined(HAVE_GETRANDOM_SYSCALL)
|
||||
#define PY_GETRANDOM 1
|
||||
|
||||
/* Call getrandom()
|
||||
|
@ -217,7 +179,43 @@ py_getrandom(void *buffer, Py_ssize_t size, int blocking, int raise)
|
|||
}
|
||||
return 1;
|
||||
}
|
||||
#endif /* defined(HAVE_GETRANDOM) || defined(HAVE_GETRANDOM_SYSCALL) */
|
||||
|
||||
#elif defined(HAVE_GETENTROPY)
|
||||
#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)
|
||||
{
|
||||
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) {
|
||||
if (raise) {
|
||||
PyErr_SetFromErrno(PyExc_OSError);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
buffer += len;
|
||||
size -= len;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
#endif /* defined(HAVE_GETENTROPY) && !defined(sun) */
|
||||
|
||||
|
||||
static struct {
|
||||
|
@ -385,13 +383,18 @@ lcg_urandom(unsigned int x0, unsigned char *buffer, size_t size)
|
|||
Used sources of entropy ordered by preference, preferred source first:
|
||||
|
||||
- CryptGenRandom() on Windows
|
||||
- getentropy() function (ex: OpenBSD): call py_getentropy()
|
||||
- getrandom() function (ex: Linux and Solaris): call py_getrandom()
|
||||
- getentropy() function (ex: OpenBSD): call py_getentropy()
|
||||
- /dev/urandom device
|
||||
|
||||
Read from the /dev/urandom device if getrandom() or getentropy() function
|
||||
is not available or does not work.
|
||||
|
||||
Prefer getrandom() over getentropy() because getrandom() supports blocking
|
||||
and non-blocking mode: see the PEP 524. Python requires non-blocking RNG at
|
||||
startup to initialize its hash secret, but os.urandom() must block until the
|
||||
system urandom is initialized (at least on Linux 3.17 and newer).
|
||||
|
||||
Prefer getrandom() and getentropy() over reading directly /dev/urandom
|
||||
because these functions don't need file descriptors and so avoid ENFILE or
|
||||
EMFILE errors (too many open files): see the issue #18756.
|
||||
|
@ -439,10 +442,10 @@ pyurandom(void *buffer, Py_ssize_t size, int blocking, int raise)
|
|||
#else
|
||||
|
||||
#if defined(PY_GETRANDOM) || defined(PY_GETENTROPY)
|
||||
#ifdef PY_GETENTROPY
|
||||
res = py_getentropy(buffer, size, raise);
|
||||
#else
|
||||
#ifdef PY_GETRANDOM
|
||||
res = py_getrandom(buffer, size, blocking, raise);
|
||||
#else
|
||||
res = py_getentropy(buffer, size, raise);
|
||||
#endif
|
||||
if (res < 0) {
|
||||
return -1;
|
||||
|
|
Loading…
Reference in New Issue