mirror of
https://github.com/python/cpython.git
synced 2025-10-14 10:53:40 +00:00
Issue #29157: enhance py_getrandom() documentation
This commit is contained in:
parent
de2f1ea124
commit
b27df6faa5
1 changed files with 20 additions and 13 deletions
|
@ -82,14 +82,18 @@ win32_urandom(unsigned char *buffer, Py_ssize_t size, int raise)
|
||||||
#if defined(HAVE_GETRANDOM) || defined(HAVE_GETRANDOM_SYSCALL)
|
#if defined(HAVE_GETRANDOM) || defined(HAVE_GETRANDOM_SYSCALL)
|
||||||
#define PY_GETRANDOM 1
|
#define PY_GETRANDOM 1
|
||||||
|
|
||||||
/* Call getrandom()
|
/* Call getrandom() to get random bytes:
|
||||||
|
|
||||||
- Return 1 on success
|
- Return 1 on success
|
||||||
- Return 0 if getrandom() syscall is not available (failed with ENOSYS or
|
- Return 0 if getrandom() is not available (failed with ENOSYS or EPERM),
|
||||||
EPERM) or if getrandom(GRND_NONBLOCK) failed with EAGAIN (system urandom
|
or if getrandom(GRND_NONBLOCK) failed with EAGAIN (system urandom not
|
||||||
not initialized yet) and raise=0.
|
initialized yet) and raise=0.
|
||||||
- Raise an exception (if raise is non-zero) and return -1 on error:
|
- Raise an exception (if raise is non-zero) and return -1 on error:
|
||||||
getrandom() failed with EINTR and the Python signal handler raised an
|
if getrandom() failed with EINTR, raise is non-zero and the Python signal
|
||||||
exception, or getrandom() failed with a different error. */
|
handler raised an exception, or if getrandom() failed with a different
|
||||||
|
error.
|
||||||
|
|
||||||
|
getrandom() is retried if it failed with EINTR: interrupted by a signal. */
|
||||||
static int
|
static int
|
||||||
py_getrandom(void *buffer, Py_ssize_t size, int blocking, int raise)
|
py_getrandom(void *buffer, Py_ssize_t size, int blocking, int raise)
|
||||||
{
|
{
|
||||||
|
@ -110,7 +114,8 @@ py_getrandom(void *buffer, Py_ssize_t size, int blocking, int raise)
|
||||||
while (0 < size) {
|
while (0 < size) {
|
||||||
#ifdef sun
|
#ifdef sun
|
||||||
/* Issue #26735: On Solaris, getrandom() is limited to returning up
|
/* Issue #26735: On Solaris, getrandom() is limited to returning up
|
||||||
to 1024 bytes */
|
to 1024 bytes. Call it multiple times if more bytes are
|
||||||
|
requested. */
|
||||||
n = Py_MIN(size, 1024);
|
n = Py_MIN(size, 1024);
|
||||||
#else
|
#else
|
||||||
n = Py_MIN(size, LONG_MAX);
|
n = Py_MIN(size, LONG_MAX);
|
||||||
|
@ -141,18 +146,19 @@ py_getrandom(void *buffer, Py_ssize_t size, int blocking, int raise)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (n < 0) {
|
if (n < 0) {
|
||||||
/* ENOSYS: getrandom() syscall not supported by the kernel (but
|
/* ENOSYS: the syscall is not supported by the kernel.
|
||||||
* maybe supported by the host which built Python). EPERM:
|
EPERM: the syscall is blocked by a security policy (ex: SECCOMP)
|
||||||
* getrandom() syscall blocked by SECCOMP or something else. */
|
or something else. */
|
||||||
if (errno == ENOSYS || errno == EPERM) {
|
if (errno == ENOSYS || errno == EPERM) {
|
||||||
getrandom_works = 0;
|
getrandom_works = 0;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* getrandom(GRND_NONBLOCK) fails with EAGAIN if the system urandom
|
/* getrandom(GRND_NONBLOCK) fails with EAGAIN if the system urandom
|
||||||
is not initialiazed yet. For _PyRandom_Init(), we ignore their
|
is not initialiazed yet. For _PyRandom_Init(), we ignore the
|
||||||
error and fall back on reading /dev/urandom which never blocks,
|
error and fall back on reading /dev/urandom which never blocks,
|
||||||
even if the system urandom is not initialized yet. */
|
even if the system urandom is not initialized yet:
|
||||||
|
see the PEP 524. */
|
||||||
if (errno == EAGAIN && !raise && !blocking) {
|
if (errno == EAGAIN && !raise && !blocking) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -313,9 +319,10 @@ dev_urandom(char *buffer, Py_ssize_t size, int raise)
|
||||||
fd = _Py_open("/dev/urandom", O_RDONLY);
|
fd = _Py_open("/dev/urandom", O_RDONLY);
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
if (errno == ENOENT || errno == ENXIO ||
|
if (errno == ENOENT || errno == ENXIO ||
|
||||||
errno == ENODEV || errno == EACCES)
|
errno == ENODEV || errno == EACCES) {
|
||||||
PyErr_SetString(PyExc_NotImplementedError,
|
PyErr_SetString(PyExc_NotImplementedError,
|
||||||
"/dev/urandom (or equivalent) not found");
|
"/dev/urandom (or equivalent) not found");
|
||||||
|
}
|
||||||
/* otherwise, keep the OSError exception raised by _Py_open() */
|
/* otherwise, keep the OSError exception raised by _Py_open() */
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue