summaryrefslogtreecommitdiffstats
path: root/Python
diff options
context:
space:
mode:
authorMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>2022-04-08 18:10:38 (GMT)
committerGitHub <noreply@github.com>2022-04-08 18:10:38 (GMT)
commit89697f7374ea947ebe8e36131e2d3e21fff6fa1d (patch)
tree6439d487c4e98b16b5ef197b7b3a9d56914f5e94 /Python
parent69edc30d2b47fe9b95975b1b66214e7473a9ccf5 (diff)
downloadcpython-89697f7374ea947ebe8e36131e2d3e21fff6fa1d.zip
cpython-89697f7374ea947ebe8e36131e2d3e21fff6fa1d.tar.gz
cpython-89697f7374ea947ebe8e36131e2d3e21fff6fa1d.tar.bz2
bpo-47260: Fix os.closerange() potentially being a no-op in a seccomp sandbox (GH-32418)
_Py_closerange() currently assumes that close_range() closes all file descriptors even if it returns an error (other than ENOSYS). This assumption can be wrong on Linux if a seccomp sandbox denies the underlying syscall, pretending that it returns EPERM or EACCES. In this case _Py_closerange() won't close any descriptors at all, which in the worst case can be a security issue. Fix this by falling back to other methods in case of any close_range() error. Note that fallbacks will not be triggered on any problems with closing individual file descriptors because close_range() is documented to ignore such errors on both Linux[1] and FreeBSD[2]. [1] https://man7.org/linux/man-pages/man2/close_range.2.html [2] https://www.freebsd.org/cgi/man.cgi?query=close_range&sektion=2 (cherry picked from commit 1c8b3b5d66a629258f1db16939b996264a8b9c37) Co-authored-by: Alexey Izbyshev <izbyshev@ispras.ru>
Diffstat (limited to 'Python')
-rw-r--r--Python/fileutils.c9
1 files changed, 5 insertions, 4 deletions
diff --git a/Python/fileutils.c b/Python/fileutils.c
index c3144ee..3b53baa 100644
--- a/Python/fileutils.c
+++ b/Python/fileutils.c
@@ -2395,10 +2395,11 @@ _Py_closerange(int first, int last)
first = Py_MAX(first, 0);
_Py_BEGIN_SUPPRESS_IPH
#ifdef HAVE_CLOSE_RANGE
- if (close_range(first, last, 0) == 0 || errno != ENOSYS) {
- /* Any errors encountered while closing file descriptors are ignored;
- * ENOSYS means no kernel support, though,
- * so we'll fallback to the other methods. */
+ if (close_range(first, last, 0) == 0) {
+ /* close_range() ignores errors when it closes file descriptors.
+ * Possible reasons of an error return are lack of kernel support
+ * or denial of the underlying syscall by a seccomp sandbox on Linux.
+ * Fallback to other methods in case of any error. */
}
else
#endif /* HAVE_CLOSE_RANGE */