[Python-checkins] cpython (2.7): Issue #23458: On POSIX, the file descriptor kept open by os.urandom() is now
victor.stinner
python-checkins at python.org
Tue Feb 24 14:32:46 CET 2015
https://hg.python.org/cpython/rev/88a99ea8a4cf
changeset: 94736:88a99ea8a4cf
branch: 2.7
parent: 94730:2b8c5ed7b38b
user: Victor Stinner <victor.stinner at gmail.com>
date: Tue Feb 24 14:30:43 2015 +0100
summary:
Issue #23458: On POSIX, the file descriptor kept open by os.urandom() is now
set to non inheritable
files:
Lib/test/subprocessdata/fd_status.py | 32 ++++++++++++++++
Lib/test/test_os.py | 28 ++++++++++++++
Misc/NEWS | 3 +
Python/random.c | 9 ++++
4 files changed, 72 insertions(+), 0 deletions(-)
diff --git a/Lib/test/subprocessdata/fd_status.py b/Lib/test/subprocessdata/fd_status.py
new file mode 100644
--- /dev/null
+++ b/Lib/test/subprocessdata/fd_status.py
@@ -0,0 +1,32 @@
+"""When called as a script, print a comma-separated list of the open
+file descriptors on stdout.
+
+Usage:
+fd_stats.py: check all file descriptors
+fd_status.py fd1 fd2 ...: check only specified file descriptors
+"""
+
+import errno
+import os
+import stat
+import sys
+
+if __name__ == "__main__":
+ fds = []
+ if len(sys.argv) == 1:
+ try:
+ _MAXFD = os.sysconf("SC_OPEN_MAX")
+ except:
+ _MAXFD = 256
+ test_fds = range(0, _MAXFD)
+ else:
+ test_fds = map(int, sys.argv[1:])
+ for fd in test_fds:
+ try:
+ st = os.fstat(fd)
+ except OSError as e:
+ if e.errno == errno.EBADF:
+ continue
+ raise
+ fds.append(fd)
+ print(','.join(map(str, fds)))
diff --git a/Lib/test/test_os.py b/Lib/test/test_os.py
--- a/Lib/test/test_os.py
+++ b/Lib/test/test_os.py
@@ -10,6 +10,7 @@
import signal
import subprocess
import sysconfig
+import textwrap
import time
try:
import resource
@@ -568,6 +569,33 @@
data2 = self.get_urandom_subprocess(16)
self.assertNotEqual(data1, data2)
+ def test_urandom_fd_non_inheritable(self):
+ # Issue #23458: os.urandom() keeps a file descriptor open, but it
+ # must be non inheritable
+ fd_status = test_support.findfile("fd_status.py", subdir="subprocessdata")
+
+ # Need a two subprocesses because the Python test suite opens other
+ # inheritable file descriptors, whereas the test is specific to
+ # os.urandom() file descriptor
+ code = textwrap.dedent("""
+ import os
+ import subprocess
+ import sys
+
+ # Ensure that the /dev/urandom file descriptor is open
+ os.urandom(1)
+
+ exitcode = subprocess.call([sys.executable, %r],
+ close_fds=False)
+ sys.exit(exitcode)
+ """ % fd_status)
+
+ proc = subprocess.Popen([sys.executable, "-c", code],
+ stdout=subprocess.PIPE, close_fds=True)
+ output, error = proc.communicate()
+ open_fds = set(map(int, output.rstrip().split(',')))
+ self.assertEqual(open_fds - set(range(3)), set())
+
HAVE_GETENTROPY = (sysconfig.get_config_var('HAVE_GETENTROPY') == 1)
diff --git a/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -18,6 +18,9 @@
Library
-------
+- Issue #23458: On POSIX, the file descriptor kept open by os.urandom() is now
+ set to non inheritable
+
- Issue #22113: struct.pack_into() now supports new buffer protocol (in
particular accepts writable memoryview).
diff --git a/Python/random.c b/Python/random.c
--- a/Python/random.c
+++ b/Python/random.c
@@ -188,6 +188,7 @@
int fd;
Py_ssize_t n;
struct stat st;
+ int attr;
if (size <= 0)
return 0;
@@ -219,6 +220,14 @@
PyErr_SetFromErrno(PyExc_OSError);
return -1;
}
+
+ /* try to make the file descriptor non-inheritable, ignore errors */
+ attr = fcntl(fd, F_GETFD);
+ if (attr >= 0) {
+ attr |= FD_CLOEXEC;
+ (void)fcntl(fd, F_SETFD, attr);
+ }
+
if (urandom_cache.fd >= 0) {
/* urandom_fd was initialized by another thread while we were
not holding the GIL, keep it. */
--
Repository URL: https://hg.python.org/cpython
More information about the Python-checkins
mailing list