mirror of
https://github.com/python/cpython.git
synced 2025-08-31 05:58:33 +00:00
parent
2f7964393d
commit
de2f1ea124
1 changed files with 39 additions and 3 deletions
|
@ -183,14 +183,31 @@ py_getrandom(void *buffer, Py_ssize_t size, int blocking, int raise)
|
||||||
#elif defined(HAVE_GETENTROPY)
|
#elif defined(HAVE_GETENTROPY)
|
||||||
#define PY_GETENTROPY 1
|
#define PY_GETENTROPY 1
|
||||||
|
|
||||||
/* Fill buffer with size pseudo-random bytes generated by getentropy().
|
/* 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. */
|
- 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
|
static int
|
||||||
py_getentropy(char *buffer, Py_ssize_t size, int raise)
|
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) {
|
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);
|
Py_ssize_t len = Py_MIN(size, 256);
|
||||||
int res;
|
int res;
|
||||||
|
|
||||||
|
@ -204,6 +221,25 @@ py_getentropy(char *buffer, Py_ssize_t size, int raise)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (res < 0) {
|
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) {
|
if (raise) {
|
||||||
PyErr_SetFromErrno(PyExc_OSError);
|
PyErr_SetFromErrno(PyExc_OSError);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue