mirror of https://github.com/python/cpython.git
parent
2f7964393d
commit
de2f1ea124
|
@ -183,14 +183,31 @@ py_getrandom(void *buffer, Py_ssize_t size, int blocking, int raise)
|
|||
#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.
|
||||
/* Fill buffer with size pseudo-random bytes generated by getentropy():
|
||||
|
||||
If raise is zero, don't raise an exception on error. */
|
||||
- Return 1 on success
|
||||
- Return 0 if getentropy() syscall is not available (failed with ENOSYS or
|
||||
EPERM).
|
||||
- Raise an exception (if raise is non-zero) and return -1 on error:
|
||||
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.
|
||||
|
||||
getentropy() is retried if it failed with EINTR: interrupted by a signal. */
|
||||
static int
|
||||
py_getentropy(char *buffer, Py_ssize_t size, int raise)
|
||||
{
|
||||
/* Is getentropy() supported by the running kernel? Set to 0 if
|
||||
getentropy() failed with ENOSYS or EPERM. */
|
||||
static int getentropy_works = 1;
|
||||
|
||||
if (!getentropy_works) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
|
@ -204,6 +221,25 @@ py_getentropy(char *buffer, Py_ssize_t size, int raise)
|
|||
}
|
||||
|
||||
if (res < 0) {
|
||||
/* ENOSYS: the syscall is not supported by the running kernel.
|
||||
EPERM: the syscall is blocked by a security policy (ex: SECCOMP)
|
||||
or something else. */
|
||||
if (errno == ENOSYS || errno == EPERM) {
|
||||
getentropy_works = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (errno == EINTR) {
|
||||
if (raise) {
|
||||
if (PyErr_CheckSignals()) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* retry getentropy() if it was interrupted by a signal */
|
||||
continue;
|
||||
}
|
||||
|
||||
if (raise) {
|
||||
PyErr_SetFromErrno(PyExc_OSError);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue