Kaydet (Commit) b27df6fa authored tarafından Victor Stinner's avatar Victor Stinner

Issue #29157: enhance py_getrandom() documentation

üst de2f1ea1
...@@ -82,14 +82,18 @@ win32_urandom(unsigned char *buffer, Py_ssize_t size, int raise) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment