diff options
author | Antoine Pitrou <solipsis@pitrou.net> | 2014-04-26 12:35:19 (GMT) |
---|---|---|
committer | Antoine Pitrou <solipsis@pitrou.net> | 2014-04-26 12:35:19 (GMT) |
commit | 4432cf45c6f0baee968a94db866b292aff50593a (patch) | |
tree | a102b781dae42c99dd7da94dc8b887f0b6cfd329 /Python | |
parent | 1c71241523a164fd631bd777b2bbc6f9af95f651 (diff) | |
parent | e472aeafc3ce2c295fed8aee1ccdad1dcaaf634e (diff) | |
download | cpython-4432cf45c6f0baee968a94db866b292aff50593a.zip cpython-4432cf45c6f0baee968a94db866b292aff50593a.tar.gz cpython-4432cf45c6f0baee968a94db866b292aff50593a.tar.bz2 |
Issue #21207: Detect when the os.urandom cached fd has been closed or replaced, and open it anew.
Diffstat (limited to 'Python')
-rw-r--r-- | Python/random.c | 49 |
1 files changed, 39 insertions, 10 deletions
diff --git a/Python/random.c b/Python/random.c index cdace00..2941ba1 100644 --- a/Python/random.c +++ b/Python/random.c @@ -3,6 +3,9 @@ #include <windows.h> #else #include <fcntl.h> +#ifdef HAVE_SYS_STAT_H +#include <sys/stat.h> +#endif #endif #ifdef Py_DEBUG @@ -69,7 +72,11 @@ win32_urandom(unsigned char *buffer, Py_ssize_t size, int raise) #ifndef MS_WINDOWS -static int urandom_fd = -1; +static struct { + int fd; + dev_t st_dev; + ino_t st_ino; +} urandom_cache = { -1 }; /* Read size bytes from /dev/urandom into buffer. Call Py_FatalError() on error. */ @@ -109,12 +116,24 @@ dev_urandom_python(char *buffer, Py_ssize_t size) { int fd; Py_ssize_t n; + struct stat st; if (size <= 0) return 0; - if (urandom_fd >= 0) - fd = urandom_fd; + if (urandom_cache.fd >= 0) { + /* Does the fd point to the same thing as before? (issue #21207) */ + if (fstat(urandom_cache.fd, &st) + || st.st_dev != urandom_cache.st_dev + || st.st_ino != urandom_cache.st_ino) { + /* Something changed: forget the cached fd (but don't close it, + since it probably points to something important for some + third-party code). */ + urandom_cache.fd = -1; + } + } + if (urandom_cache.fd >= 0) + fd = urandom_cache.fd; else { Py_BEGIN_ALLOW_THREADS fd = _Py_open("/dev/urandom", O_RDONLY); @@ -129,14 +148,24 @@ dev_urandom_python(char *buffer, Py_ssize_t size) PyErr_SetFromErrno(PyExc_OSError); return -1; } - if (urandom_fd >= 0) { + if (urandom_cache.fd >= 0) { /* urandom_fd was initialized by another thread while we were not holding the GIL, keep it. */ close(fd); - fd = urandom_fd; + fd = urandom_cache.fd; + } + else { + if (fstat(fd, &st)) { + PyErr_SetFromErrno(PyExc_OSError); + close(fd); + return -1; + } + else { + urandom_cache.fd = fd; + urandom_cache.st_dev = st.st_dev; + urandom_cache.st_ino = st.st_ino; + } } - else - urandom_fd = fd; } Py_BEGIN_ALLOW_THREADS @@ -168,9 +197,9 @@ dev_urandom_python(char *buffer, Py_ssize_t size) static void dev_urandom_close(void) { - if (urandom_fd >= 0) { - close(urandom_fd); - urandom_fd = -1; + if (urandom_cache.fd >= 0) { + close(urandom_cache.fd); + urandom_cache.fd = -1; } } |