diff --git a/00397-tarfile-filter.patch b/00397-tarfile-filter.patch index 0bf2f50..135c595 100644 --- a/00397-tarfile-filter.patch +++ b/00397-tarfile-filter.patch @@ -1,3 +1,113 @@ +From f36519078bde3cce4328c03fffccb846121fb5bc Mon Sep 17 00:00:00 2001 +From: Petr Viktorin +Date: Wed, 9 Aug 2023 20:23:03 +0200 +Subject: [PATCH] Fix symlink handling for tarfile.data_filter + +--- + Doc/library/tarfile.rst | 5 +++++ + Lib/tarfile.py | 9 ++++++++- + Lib/test/test_tarfile.py | 26 ++++++++++++++++++++++++-- + 3 files changed, 37 insertions(+), 3 deletions(-) + +diff --git a/Doc/library/tarfile.rst b/Doc/library/tarfile.rst +index 00f3070324e..e0511bfeb64 100644 +--- a/Doc/library/tarfile.rst ++++ b/Doc/library/tarfile.rst +@@ -740,6 +740,11 @@ A ``TarInfo`` object has the following public data attributes: + Name of the target file name, which is only present in :class:`TarInfo` objects + of type :const:`LNKTYPE` and :const:`SYMTYPE`. + ++ For symbolic links (``SYMTYPE``), the linkname is relative to the directory ++ that contains the link. ++ For hard links (``LNKTYPE``), the linkname is relative to the root of ++ the archive. ++ + + .. attribute:: TarInfo.uid + :type: int +diff --git a/Lib/tarfile.py b/Lib/tarfile.py +index df4e41f7a0d..d62323715b4 100755 +--- a/Lib/tarfile.py ++++ b/Lib/tarfile.py +@@ -802,7 +802,14 @@ def _get_filtered_attrs(member, dest_path, for_data=True): + if member.islnk() or member.issym(): + if os.path.isabs(member.linkname): + raise AbsoluteLinkError(member) +- target_path = os.path.realpath(os.path.join(dest_path, member.linkname)) ++ if member.issym(): ++ target_path = os.path.join(dest_path, ++ os.path.dirname(name), ++ member.linkname) ++ else: ++ target_path = os.path.join(dest_path, ++ member.linkname) ++ target_path = os.path.realpath(target_path) + if os.path.commonpath([target_path, dest_path]) != dest_path: + raise LinkOutsideDestinationError(member, target_path) + return new_attrs +diff --git a/Lib/test/test_tarfile.py b/Lib/test/test_tarfile.py +index 2eda7fc4cea..79fc35c2895 100644 +--- a/Lib/test/test_tarfile.py ++++ b/Lib/test/test_tarfile.py +@@ -3337,10 +3337,12 @@ def __exit__(self, *exc): + self.bio = None + + def add(self, name, *, type=None, symlink_to=None, hardlink_to=None, +- mode=None, **kwargs): ++ mode=None, size=None, **kwargs): + """Add a member to the test archive. Call within `with`.""" + name = str(name) + tarinfo = tarfile.TarInfo(name).replace(**kwargs) ++ if size is not None: ++ tarinfo.size = size + if mode: + tarinfo.mode = _filemode_to_int(mode) + if symlink_to is not None: +@@ -3416,7 +3418,8 @@ def check_context(self, tar, filter): + raise self.raised_exception + self.assertEqual(self.expected_paths, set()) + +- def expect_file(self, name, type=None, symlink_to=None, mode=None): ++ def expect_file(self, name, type=None, symlink_to=None, mode=None, ++ size=None): + """Check a single file. See check_context.""" + if self.raised_exception: + raise self.raised_exception +@@ -3445,6 +3448,8 @@ def expect_file(self, name, type=None, symlink_to=None, mode=None): + self.assertTrue(path.is_fifo()) + else: + raise NotImplementedError(type) ++ if size is not None: ++ self.assertEqual(path.stat().st_size, size) + for parent in path.parents: + self.expected_paths.discard(parent) + +@@ -3649,6 +3654,22 @@ def test_sly_relative2(self): + + """['"].*moo['"], which is outside the """ + + "destination") + ++ def test_deep_symlink(self): ++ with ArchiveMaker() as arc: ++ arc.add('targetdir/target', size=3) ++ arc.add('linkdir/hardlink', hardlink_to='targetdir/target') ++ arc.add('linkdir/symlink', symlink_to='../targetdir/target') ++ ++ for filter in 'tar', 'data', 'fully_trusted': ++ with self.check_context(arc.open(), filter): ++ self.expect_file('targetdir/target', size=3) ++ self.expect_file('linkdir/hardlink', size=3) ++ if support.can_symlink(): ++ self.expect_file('linkdir/symlink', size=3, ++ symlink_to='../targetdir/target') ++ else: ++ self.expect_file('linkdir/symlink', size=3) ++ + def test_modes(self): + # Test how file modes are extracted + # (Note that the modes are ignored on platforms without working chmod) +-- +2.41.0 + From dc84087083c5ad99a5016e8349c96d9654a08f46 Mon Sep 17 00:00:00 2001 From: Petr Viktorin Date: Mon, 6 Mar 2023 17:24:24 +0100 diff --git a/python38.spec b/python38.spec index a0b6b82..bac3497 100644 --- a/python38.spec +++ b/python38.spec @@ -17,7 +17,7 @@ URL: https://www.python.org/ #global prerel ... %global upstream_version %{general_version}%{?prerel} Version: %{general_version}%{?prerel:~%{prerel}} -Release: 1%{?dist} +Release: 2%{?dist} License: Python # Exclude i686 arch. Due to a modularity issue it's being added to the @@ -383,8 +383,12 @@ Patch359: 00359-CVE-2021-23336.patch Patch378: 00378-support-expat-2-4-5.patch # 00397 # -# Add Red Hat configuration for tarfile extraction (CVE-2007-4559, PEP-706) -# See KB for documentation: +# Add filters for tarfile extraction (CVE-2007-4559, PEP-706) +# First patch fixes determination of symlink targets, which were treated +# as relative to the root of the archive, +# rather than the directory containing the symlink. +# Not yet upstream as of this writing. +# The second patch is Red Hat configuration, see KB for documentation: # - https://access.redhat.com/articles/7004769 Patch397: 00397-tarfile-filter.patch @@ -1839,6 +1843,10 @@ fi # ====================================================== %changelog +* Wed Aug 09 2023 Petr Viktorin - 3.8.17-2 +- Fix symlink handling in the fix for CVE-2023-24329 +Resolves: rhbz#263261 + * Mon Aug 07 2023 Charalampos Stratakis - 3.8.17-1 - Update to 3.8.17 - Security fix for CVE-2023-24329