diff options
author | Alexey Izbyshev <izbyshev@ispras.ru> | 2022-04-08 17:40:39 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-04-08 17:40:39 (GMT) |
commit | 1c8b3b5d66a629258f1db16939b996264a8b9c37 (patch) | |
tree | 114d4b1e1f26ee192f292a81438baac1d80e78f5 /Python | |
parent | d6fb104690cdeeea04ecbaf5c9bcafc622e03648 (diff) | |
download | cpython-1c8b3b5d66a629258f1db16939b996264a8b9c37.zip cpython-1c8b3b5d66a629258f1db16939b996264a8b9c37.tar.gz cpython-1c8b3b5d66a629258f1db16939b996264a8b9c37.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
Diffstat (limited to 'Python')
-rw-r--r-- | Python/fileutils.c | 9 |
1 files changed, 5 insertions, 4 deletions
diff --git a/Python/fileutils.c b/Python/fileutils.c index 111d7fa..d1d62dc 100644 --- a/Python/fileutils.c +++ b/Python/fileutils.c @@ -2624,10 +2624,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 */ |