forked from pool/python310
Set link to python310.32817 via maintenance_release request
This commit is contained in:
191
CVE-2023-6597-TempDir-cleaning-symlink.patch
Normal file
191
CVE-2023-6597-TempDir-cleaning-symlink.patch
Normal file
@@ -0,0 +1,191 @@
|
|||||||
|
---
|
||||||
|
Lib/tempfile.py | 26 +-
|
||||||
|
Lib/test/test_tempfile.py | 117 +++++++++-
|
||||||
|
Misc/NEWS.d/next/Library/2022-12-01-16-57-44.gh-issue-91133.LKMVCV.rst | 2
|
||||||
|
3 files changed, 136 insertions(+), 9 deletions(-)
|
||||||
|
|
||||||
|
--- a/Lib/tempfile.py
|
||||||
|
+++ b/Lib/tempfile.py
|
||||||
|
@@ -269,6 +269,22 @@ def _mkstemp_inner(dir, pre, suf, flags,
|
||||||
|
raise FileExistsError(_errno.EEXIST,
|
||||||
|
"No usable temporary file name found")
|
||||||
|
|
||||||
|
+def _dont_follow_symlinks(func, path, *args):
|
||||||
|
+ # Pass follow_symlinks=False, unless not supported on this platform.
|
||||||
|
+ if func in _os.supports_follow_symlinks:
|
||||||
|
+ func(path, *args, follow_symlinks=False)
|
||||||
|
+ elif _os.name == 'nt' or not _os.path.islink(path):
|
||||||
|
+ func(path, *args)
|
||||||
|
+
|
||||||
|
+def _resetperms(path):
|
||||||
|
+ try:
|
||||||
|
+ chflags = _os.chflags
|
||||||
|
+ except AttributeError:
|
||||||
|
+ pass
|
||||||
|
+ else:
|
||||||
|
+ _dont_follow_symlinks(chflags, path, 0)
|
||||||
|
+ _dont_follow_symlinks(_os.chmod, path, 0o700)
|
||||||
|
+
|
||||||
|
|
||||||
|
# User visible interfaces.
|
||||||
|
|
||||||
|
@@ -827,17 +843,11 @@ class TemporaryDirectory:
|
||||||
|
def _rmtree(cls, name, ignore_errors=False):
|
||||||
|
def onerror(func, path, exc_info):
|
||||||
|
if issubclass(exc_info[0], PermissionError):
|
||||||
|
- def resetperms(path):
|
||||||
|
- try:
|
||||||
|
- _os.chflags(path, 0)
|
||||||
|
- except AttributeError:
|
||||||
|
- pass
|
||||||
|
- _os.chmod(path, 0o700)
|
||||||
|
|
||||||
|
try:
|
||||||
|
if path != name:
|
||||||
|
- resetperms(_os.path.dirname(path))
|
||||||
|
- resetperms(path)
|
||||||
|
+ _resetperms(_os.path.dirname(path))
|
||||||
|
+ _resetperms(path)
|
||||||
|
|
||||||
|
try:
|
||||||
|
_os.unlink(path)
|
||||||
|
--- a/Lib/test/test_tempfile.py
|
||||||
|
+++ b/Lib/test/test_tempfile.py
|
||||||
|
@@ -1499,6 +1499,103 @@ class TestTemporaryDirectory(BaseTestCas
|
||||||
|
"were deleted")
|
||||||
|
d2.cleanup()
|
||||||
|
|
||||||
|
+ @os_helper.skip_unless_symlink
|
||||||
|
+ def test_cleanup_with_symlink_modes(self):
|
||||||
|
+ # cleanup() should not follow symlinks when fixing mode bits (#91133)
|
||||||
|
+ with self.do_create(recurse=0) as d2:
|
||||||
|
+ file1 = os.path.join(d2, 'file1')
|
||||||
|
+ open(file1, 'wb').close()
|
||||||
|
+ dir1 = os.path.join(d2, 'dir1')
|
||||||
|
+ os.mkdir(dir1)
|
||||||
|
+ for mode in range(8):
|
||||||
|
+ mode <<= 6
|
||||||
|
+ with self.subTest(mode=format(mode, '03o')):
|
||||||
|
+ def test(target, target_is_directory):
|
||||||
|
+ d1 = self.do_create(recurse=0)
|
||||||
|
+ symlink = os.path.join(d1.name, 'symlink')
|
||||||
|
+ os.symlink(target, symlink,
|
||||||
|
+ target_is_directory=target_is_directory)
|
||||||
|
+ try:
|
||||||
|
+ os.chmod(symlink, mode, follow_symlinks=False)
|
||||||
|
+ except NotImplementedError:
|
||||||
|
+ pass
|
||||||
|
+ try:
|
||||||
|
+ os.chmod(symlink, mode)
|
||||||
|
+ except FileNotFoundError:
|
||||||
|
+ pass
|
||||||
|
+ os.chmod(d1.name, mode)
|
||||||
|
+ d1.cleanup()
|
||||||
|
+ self.assertFalse(os.path.exists(d1.name))
|
||||||
|
+
|
||||||
|
+ with self.subTest('nonexisting file'):
|
||||||
|
+ test('nonexisting', target_is_directory=False)
|
||||||
|
+ with self.subTest('nonexisting dir'):
|
||||||
|
+ test('nonexisting', target_is_directory=True)
|
||||||
|
+
|
||||||
|
+ with self.subTest('existing file'):
|
||||||
|
+ os.chmod(file1, mode)
|
||||||
|
+ old_mode = os.stat(file1).st_mode
|
||||||
|
+ test(file1, target_is_directory=False)
|
||||||
|
+ new_mode = os.stat(file1).st_mode
|
||||||
|
+ self.assertEqual(new_mode, old_mode,
|
||||||
|
+ '%03o != %03o' % (new_mode, old_mode))
|
||||||
|
+
|
||||||
|
+ with self.subTest('existing dir'):
|
||||||
|
+ os.chmod(dir1, mode)
|
||||||
|
+ old_mode = os.stat(dir1).st_mode
|
||||||
|
+ test(dir1, target_is_directory=True)
|
||||||
|
+ new_mode = os.stat(dir1).st_mode
|
||||||
|
+ self.assertEqual(new_mode, old_mode,
|
||||||
|
+ '%03o != %03o' % (new_mode, old_mode))
|
||||||
|
+
|
||||||
|
+ @unittest.skipUnless(hasattr(os, 'chflags'), 'requires os.chflags')
|
||||||
|
+ @os_helper.skip_unless_symlink
|
||||||
|
+ def test_cleanup_with_symlink_flags(self):
|
||||||
|
+ # cleanup() should not follow symlinks when fixing flags (#91133)
|
||||||
|
+ flags = stat.UF_IMMUTABLE | stat.UF_NOUNLINK
|
||||||
|
+ self.check_flags(flags)
|
||||||
|
+
|
||||||
|
+ with self.do_create(recurse=0) as d2:
|
||||||
|
+ file1 = os.path.join(d2, 'file1')
|
||||||
|
+ open(file1, 'wb').close()
|
||||||
|
+ dir1 = os.path.join(d2, 'dir1')
|
||||||
|
+ os.mkdir(dir1)
|
||||||
|
+ def test(target, target_is_directory):
|
||||||
|
+ d1 = self.do_create(recurse=0)
|
||||||
|
+ symlink = os.path.join(d1.name, 'symlink')
|
||||||
|
+ os.symlink(target, symlink,
|
||||||
|
+ target_is_directory=target_is_directory)
|
||||||
|
+ try:
|
||||||
|
+ os.chflags(symlink, flags, follow_symlinks=False)
|
||||||
|
+ except NotImplementedError:
|
||||||
|
+ pass
|
||||||
|
+ try:
|
||||||
|
+ os.chflags(symlink, flags)
|
||||||
|
+ except FileNotFoundError:
|
||||||
|
+ pass
|
||||||
|
+ os.chflags(d1.name, flags)
|
||||||
|
+ d1.cleanup()
|
||||||
|
+ self.assertFalse(os.path.exists(d1.name))
|
||||||
|
+
|
||||||
|
+ with self.subTest('nonexisting file'):
|
||||||
|
+ test('nonexisting', target_is_directory=False)
|
||||||
|
+ with self.subTest('nonexisting dir'):
|
||||||
|
+ test('nonexisting', target_is_directory=True)
|
||||||
|
+
|
||||||
|
+ with self.subTest('existing file'):
|
||||||
|
+ os.chflags(file1, flags)
|
||||||
|
+ old_flags = os.stat(file1).st_flags
|
||||||
|
+ test(file1, target_is_directory=False)
|
||||||
|
+ new_flags = os.stat(file1).st_flags
|
||||||
|
+ self.assertEqual(new_flags, old_flags)
|
||||||
|
+
|
||||||
|
+ with self.subTest('existing dir'):
|
||||||
|
+ os.chflags(dir1, flags)
|
||||||
|
+ old_flags = os.stat(dir1).st_flags
|
||||||
|
+ test(dir1, target_is_directory=True)
|
||||||
|
+ new_flags = os.stat(dir1).st_flags
|
||||||
|
+ self.assertEqual(new_flags, old_flags)
|
||||||
|
+
|
||||||
|
@support.cpython_only
|
||||||
|
def test_del_on_collection(self):
|
||||||
|
# A TemporaryDirectory is deleted when garbage collected
|
||||||
|
@@ -1671,9 +1768,27 @@ class TestTemporaryDirectory(BaseTestCas
|
||||||
|
d.cleanup()
|
||||||
|
self.assertFalse(os.path.exists(d.name))
|
||||||
|
|
||||||
|
- @unittest.skipUnless(hasattr(os, 'chflags'), 'requires os.lchflags')
|
||||||
|
+ def check_flags(self, flags):
|
||||||
|
+ # skip the test if these flags are not supported (ex: FreeBSD 13)
|
||||||
|
+ filename = os_helper.TESTFN
|
||||||
|
+ try:
|
||||||
|
+ open(filename, "w").close()
|
||||||
|
+ try:
|
||||||
|
+ os.chflags(filename, flags)
|
||||||
|
+ except OSError as exc:
|
||||||
|
+ # "OSError: [Errno 45] Operation not supported"
|
||||||
|
+ self.skipTest(f"chflags() doesn't support flags "
|
||||||
|
+ f"{flags:#b}: {exc}")
|
||||||
|
+ else:
|
||||||
|
+ os.chflags(filename, 0)
|
||||||
|
+ finally:
|
||||||
|
+ support.unlink(filename)
|
||||||
|
+
|
||||||
|
+ @unittest.skipUnless(hasattr(os, 'chflags'), 'requires os.chflags')
|
||||||
|
def test_flags(self):
|
||||||
|
flags = stat.UF_IMMUTABLE | stat.UF_NOUNLINK
|
||||||
|
+ self.check_flags(flags)
|
||||||
|
+
|
||||||
|
d = self.do_create(recurse=3, dirs=2, files=2)
|
||||||
|
with d:
|
||||||
|
# Change files and directories flags recursively.
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/Misc/NEWS.d/next/Library/2022-12-01-16-57-44.gh-issue-91133.LKMVCV.rst
|
||||||
|
@@ -0,0 +1,2 @@
|
||||||
|
+Fix a bug in :class:`tempfile.TemporaryDirectory` cleanup, which now no longer
|
||||||
|
+dereferences symlinks when working around file system permission errors.
|
||||||
107
libexpat260.patch
Normal file
107
libexpat260.patch
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
From f2eebf3c38eae77765247791576b437ec25ccfe2 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Serhiy Storchaka <storchaka@gmail.com>
|
||||||
|
Date: Sun, 11 Feb 2024 12:08:39 +0200
|
||||||
|
Subject: [PATCH] gh-115133: Fix tests for XMLPullParser with Expat 2.6.0
|
||||||
|
(GH-115164)
|
||||||
|
|
||||||
|
Feeding the parser by too small chunks defers parsing to prevent
|
||||||
|
CVE-2023-52425. Future versions of Expat may be more reactive.
|
||||||
|
(cherry picked from commit 4a08e7b3431cd32a0daf22a33421cd3035343dc4)
|
||||||
|
|
||||||
|
Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
|
||||||
|
---
|
||||||
|
Lib/test/test_xml_etree.py | 58 ++++++++++++-------
|
||||||
|
...-02-08-14-21-28.gh-issue-115133.ycl4ko.rst | 2 +
|
||||||
|
2 files changed, 38 insertions(+), 22 deletions(-)
|
||||||
|
create mode 100644 Misc/NEWS.d/next/Library/2024-02-08-14-21-28.gh-issue-115133.ycl4ko.rst
|
||||||
|
|
||||||
|
Index: Python-3.10.13/Lib/test/test_xml_etree.py
|
||||||
|
===================================================================
|
||||||
|
--- Python-3.10.13.orig/Lib/test/test_xml_etree.py
|
||||||
|
+++ Python-3.10.13/Lib/test/test_xml_etree.py
|
||||||
|
@@ -13,6 +13,7 @@ import itertools
|
||||||
|
import operator
|
||||||
|
import os
|
||||||
|
import pickle
|
||||||
|
+import pyexpat
|
||||||
|
import sys
|
||||||
|
import textwrap
|
||||||
|
import types
|
||||||
|
@@ -120,6 +121,10 @@ ATTLIST_XML = """\
|
||||||
|
</foo>
|
||||||
|
"""
|
||||||
|
|
||||||
|
+fails_with_expat_2_6_0 = (unittest.expectedFailure
|
||||||
|
+ if pyexpat.version_info >= (2, 6, 0) else
|
||||||
|
+ lambda test: test)
|
||||||
|
+
|
||||||
|
def checkwarnings(*filters, quiet=False):
|
||||||
|
def decorator(test):
|
||||||
|
def newtest(*args, **kwargs):
|
||||||
|
@@ -1396,28 +1401,37 @@ class XMLPullParserTest(unittest.TestCas
|
||||||
|
self.assertEqual([(action, elem.tag) for action, elem in events],
|
||||||
|
expected)
|
||||||
|
|
||||||
|
- def test_simple_xml(self):
|
||||||
|
- for chunk_size in (None, 1, 5):
|
||||||
|
- with self.subTest(chunk_size=chunk_size):
|
||||||
|
- parser = ET.XMLPullParser()
|
||||||
|
- self.assert_event_tags(parser, [])
|
||||||
|
- self._feed(parser, "<!-- comment -->\n", chunk_size)
|
||||||
|
- self.assert_event_tags(parser, [])
|
||||||
|
- self._feed(parser,
|
||||||
|
- "<root>\n <element key='value'>text</element",
|
||||||
|
- chunk_size)
|
||||||
|
- self.assert_event_tags(parser, [])
|
||||||
|
- self._feed(parser, ">\n", chunk_size)
|
||||||
|
- self.assert_event_tags(parser, [('end', 'element')])
|
||||||
|
- self._feed(parser, "<element>text</element>tail\n", chunk_size)
|
||||||
|
- self._feed(parser, "<empty-element/>\n", chunk_size)
|
||||||
|
- self.assert_event_tags(parser, [
|
||||||
|
- ('end', 'element'),
|
||||||
|
- ('end', 'empty-element'),
|
||||||
|
- ])
|
||||||
|
- self._feed(parser, "</root>\n", chunk_size)
|
||||||
|
- self.assert_event_tags(parser, [('end', 'root')])
|
||||||
|
- self.assertIsNone(parser.close())
|
||||||
|
+ def test_simple_xml(self, chunk_size=None):
|
||||||
|
+ parser = ET.XMLPullParser()
|
||||||
|
+ self.assert_event_tags(parser, [])
|
||||||
|
+ self._feed(parser, "<!-- comment -->\n", chunk_size)
|
||||||
|
+ self.assert_event_tags(parser, [])
|
||||||
|
+ self._feed(parser,
|
||||||
|
+ "<root>\n <element key='value'>text</element",
|
||||||
|
+ chunk_size)
|
||||||
|
+ self.assert_event_tags(parser, [])
|
||||||
|
+ self._feed(parser, ">\n", chunk_size)
|
||||||
|
+ self.assert_event_tags(parser, [('end', 'element')])
|
||||||
|
+ self._feed(parser, "<element>text</element>tail\n", chunk_size)
|
||||||
|
+ self._feed(parser, "<empty-element/>\n", chunk_size)
|
||||||
|
+ self.assert_event_tags(parser, [
|
||||||
|
+ ('end', 'element'),
|
||||||
|
+ ('end', 'empty-element'),
|
||||||
|
+ ])
|
||||||
|
+ self._feed(parser, "</root>\n", chunk_size)
|
||||||
|
+ self.assert_event_tags(parser, [('end', 'root')])
|
||||||
|
+ self.assertIsNone(parser.close())
|
||||||
|
+
|
||||||
|
+ @fails_with_expat_2_6_0
|
||||||
|
+ def test_simple_xml_chunk_1(self):
|
||||||
|
+ self.test_simple_xml(chunk_size=1)
|
||||||
|
+
|
||||||
|
+ @fails_with_expat_2_6_0
|
||||||
|
+ def test_simple_xml_chunk_5(self):
|
||||||
|
+ self.test_simple_xml(chunk_size=5)
|
||||||
|
+
|
||||||
|
+ def test_simple_xml_chunk_22(self):
|
||||||
|
+ self.test_simple_xml(chunk_size=22)
|
||||||
|
|
||||||
|
def test_feed_while_iterating(self):
|
||||||
|
parser = ET.XMLPullParser()
|
||||||
|
Index: Python-3.10.13/Misc/NEWS.d/next/Library/2024-02-08-14-21-28.gh-issue-115133.ycl4ko.rst
|
||||||
|
===================================================================
|
||||||
|
--- /dev/null
|
||||||
|
+++ Python-3.10.13/Misc/NEWS.d/next/Library/2024-02-08-14-21-28.gh-issue-115133.ycl4ko.rst
|
||||||
|
@@ -0,0 +1,2 @@
|
||||||
|
+Fix tests for :class:`~xml.etree.ElementTree.XMLPullParser` with Expat
|
||||||
|
+2.6.0.
|
||||||
@@ -1,3 +1,23 @@
|
|||||||
|
-------------------------------------------------------------------
|
||||||
|
Fri Feb 23 01:06:42 UTC 2024 - Matej Cepl <mcepl@suse.com>
|
||||||
|
|
||||||
|
- (bsc#1219666, CVE-2023-6597) Add
|
||||||
|
CVE-2023-6597-TempDir-cleaning-symlink.patch (patch from
|
||||||
|
gh#python/cpython!99930) fixing symlink bug in cleanup of
|
||||||
|
tempfile.TemporaryDirectory.
|
||||||
|
|
||||||
|
-------------------------------------------------------------------
|
||||||
|
Tue Feb 20 22:14:02 UTC 2024 - Matej Cepl <mcepl@cepl.eu>
|
||||||
|
|
||||||
|
- Remove double definition of /usr/bin/idle%%{version} in
|
||||||
|
%%files.
|
||||||
|
|
||||||
|
-------------------------------------------------------------------
|
||||||
|
Thu Feb 15 10:29:07 UTC 2024 - Daniel Garcia <daniel.garcia@suse.com>
|
||||||
|
|
||||||
|
- Add upstream patch libexpat260.patch, Fix tests for XMLPullParser
|
||||||
|
with Expat 2.6.0, gh#python/cpython#115289
|
||||||
|
|
||||||
-------------------------------------------------------------------
|
-------------------------------------------------------------------
|
||||||
Mon Dec 18 16:20:58 UTC 2023 - Matej Cepl <mcepl@cepl.eu>
|
Mon Dec 18 16:20:58 UTC 2023 - Matej Cepl <mcepl@cepl.eu>
|
||||||
|
|
||||||
|
|||||||
@@ -191,6 +191,12 @@ Patch40: CVE-2023-27043-email-parsing-errors.patch
|
|||||||
# * gh#python/cpython#104221
|
# * gh#python/cpython#104221
|
||||||
# * gh#python/cpython#107246
|
# * gh#python/cpython#107246
|
||||||
Patch42: fix-sphinx-72.patch
|
Patch42: fix-sphinx-72.patch
|
||||||
|
# PATCH-FIX-UPSTREAM libexpat260.patch gh#python/cpython#115289
|
||||||
|
# Fix tests for XMLPullParser with Expat 2.6.0
|
||||||
|
Patch43: libexpat260.patch
|
||||||
|
# PATCH-FIX-UPSTREAM CVE-2023-6597-TempDir-cleaning-symlink.patch bsc#1219666 mcepl@suse.com
|
||||||
|
# tempfile.TemporaryDirectory: fix symlink bug in cleanup (from gh#python/cpython!99930)
|
||||||
|
Patch44: CVE-2023-6597-TempDir-cleaning-symlink.patch
|
||||||
BuildRequires: autoconf-archive
|
BuildRequires: autoconf-archive
|
||||||
BuildRequires: automake
|
BuildRequires: automake
|
||||||
BuildRequires: fdupes
|
BuildRequires: fdupes
|
||||||
@@ -449,23 +455,25 @@ other applications.
|
|||||||
|
|
||||||
%prep
|
%prep
|
||||||
%setup -q -n %{tarname}
|
%setup -q -n %{tarname}
|
||||||
%patch02 -p1
|
%patch -P 02 -p1
|
||||||
%patch06 -p1
|
%patch -P 06 -p1
|
||||||
%patch07 -p1
|
%patch -P 07 -p1
|
||||||
%patch08 -p1
|
%patch -P 08 -p1
|
||||||
%patch09 -p1
|
%patch -P 09 -p1
|
||||||
%patch15 -p1
|
%patch -P 15 -p1
|
||||||
%patch29 -p1
|
%patch -P 29 -p1
|
||||||
%if 0%{?sle_version} && 0%{?sle_version} <= 150300
|
%if 0%{?sle_version} && 0%{?sle_version} <= 150300
|
||||||
%patch33 -p1
|
%patch -P 33 -p1
|
||||||
%patch34 -p1
|
%patch -P 34 -p1
|
||||||
%endif
|
%endif
|
||||||
%patch35 -p1
|
%patch -P 35 -p1
|
||||||
%patch36 -p1
|
%patch -P 36 -p1
|
||||||
%patch38 -p1
|
%patch -P 38 -p1
|
||||||
%patch39 -p1
|
%patch -P 39 -p1
|
||||||
%patch40 -p1
|
%patch -P 40 -p1
|
||||||
%patch42 -p1
|
%patch -P 42 -p1
|
||||||
|
%patch -P 43 -p1
|
||||||
|
%patch -P 44 -p1
|
||||||
|
|
||||||
# drop Autoconf version requirement
|
# drop Autoconf version requirement
|
||||||
sed -i 's/^AC_PREREQ/dnl AC_PREREQ/' configure.ac
|
sed -i 's/^AC_PREREQ/dnl AC_PREREQ/' configure.ac
|
||||||
@@ -848,7 +856,6 @@ echo %{sitedir}/_import_failed > %{buildroot}/%{sitedir}/site-packages/zzzz-impo
|
|||||||
%dir %{_datadir}/icons/hicolor/32x32
|
%dir %{_datadir}/icons/hicolor/32x32
|
||||||
%dir %{_datadir}/icons/hicolor/48x48
|
%dir %{_datadir}/icons/hicolor/48x48
|
||||||
%dir %{_datadir}/icons/hicolor/*/apps
|
%dir %{_datadir}/icons/hicolor/*/apps
|
||||||
%attr(755, root, root) %{_bindir}/idle%{python_version}
|
|
||||||
# endif for if general
|
# endif for if general
|
||||||
%endif
|
%endif
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user