diff --git a/backport-CVE-2023-6597-gh-91133-tempfile.TemporaryDirectory-fix-symlin.patch b/backport-CVE-2023-6597-gh-91133-tempfile.TemporaryDirectory-fix-symlin.patch new file mode 100644 index 0000000000000000000000000000000000000000..d931cac779ce6ca8880c22c5963d1b9bee77ea4a --- /dev/null +++ b/backport-CVE-2023-6597-gh-91133-tempfile.TemporaryDirectory-fix-symlin.patch @@ -0,0 +1,218 @@ +From 5585334d772b253a01a6730e8202ffb1607c3d25 Mon Sep 17 00:00:00 2001 +From: Serhiy Storchaka +Date: Thu, 7 Dec 2023 18:37:10 +0200 +Subject: [PATCH] [3.11] gh-91133: tempfile.TemporaryDirectory: fix symlink bug + in cleanup (GH-99930) (GH-112839) +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +(cherry picked from commit 81c16cd94ec38d61aa478b9a452436dc3b1b524d) + +Co-authored-by: Søren Løvborg +--- + Lib/tempfile.py | 27 +++-- + Lib/test/test_tempfile.py | 111 +++++++++++++++++- + ...2-12-01-16-57-44.gh-issue-91133.LKMVCV.rst | 2 + + 3 files changed, 125 insertions(+), 15 deletions(-) + create mode 100644 Misc/NEWS.d/next/Library/2022-12-01-16-57-44.gh-issue-91133.LKMVCV.rst + +diff --git a/Lib/tempfile.py b/Lib/tempfile.py +index aace11fa7b1..f59a63a7b45 100644 +--- a/Lib/tempfile.py ++++ b/Lib/tempfile.py +@@ -270,6 +270,22 @@ def _mkstemp_inner(dir, pre, suf, flags, output_type): + 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. + +@@ -863,17 +879,10 @@ def __init__(self, suffix=None, prefix=None, dir=None, + 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) +diff --git a/Lib/test/test_tempfile.py b/Lib/test/test_tempfile.py +index 1242ec7e3cc..675edc8de9c 100644 +--- a/Lib/test/test_tempfile.py ++++ b/Lib/test/test_tempfile.py +@@ -1565,6 +1565,103 @@ def test_cleanup_with_symlink_to_a_directory(self): + "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 +@@ -1737,10 +1834,7 @@ def test_modes(self): + d.cleanup() + self.assertFalse(os.path.exists(d.name)) + +- @unittest.skipUnless(hasattr(os, 'chflags'), 'requires os.chflags') +- def test_flags(self): +- flags = stat.UF_IMMUTABLE | stat.UF_NOUNLINK +- ++ def check_flags(self, flags): + # skip the test if these flags are not supported (ex: FreeBSD 13) + filename = os_helper.TESTFN + try: +@@ -1749,13 +1843,18 @@ def test_flags(self): + os.chflags(filename, flags) + except OSError as exc: + # "OSError: [Errno 45] Operation not supported" +- self.skipTest(f"chflags() doesn't support " +- f"UF_IMMUTABLE|UF_NOUNLINK: {exc}") ++ self.skipTest(f"chflags() doesn't support flags " ++ f"{flags:#b}: {exc}") + else: + os.chflags(filename, 0) + finally: + os_helper.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. +diff --git a/Misc/NEWS.d/next/Library/2022-12-01-16-57-44.gh-issue-91133.LKMVCV.rst b/Misc/NEWS.d/next/Library/2022-12-01-16-57-44.gh-issue-91133.LKMVCV.rst +new file mode 100644 +index 00000000000..7991048fc48 +--- /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. +-- +2.33.0 + diff --git a/backport-3.11-gh-114572-Fix-locking-in-cert_store_stats-and-g.patch b/backport-CVE-2024-0397-gh-114572-Fix-locking-in-cert_store_stats-and-g.patch similarity index 100% rename from backport-3.11-gh-114572-Fix-locking-in-cert_store_stats-and-g.patch rename to backport-CVE-2024-0397-gh-114572-Fix-locking-in-cert_store_stats-and-g.patch diff --git a/backport-CVE-2024-0450-gh-109858-Protect-zipfile-from-quoted-overlap-z.patch b/backport-CVE-2024-0450-gh-109858-Protect-zipfile-from-quoted-overlap-z.patch new file mode 100644 index 0000000000000000000000000000000000000000..03e5cc10774dff1aaa095b35b2164f3ac6635a91 --- /dev/null +++ b/backport-CVE-2024-0450-gh-109858-Protect-zipfile-from-quoted-overlap-z.patch @@ -0,0 +1,146 @@ +From a956e510f6336d5ae111ba429a61c3ade30a7549 Mon Sep 17 00:00:00 2001 +From: "Miss Islington (bot)" + <31488909+miss-islington@users.noreply.github.com> +Date: Thu, 11 Jan 2024 10:24:47 +0100 +Subject: [PATCH] [3.11] gh-109858: Protect zipfile from "quoted-overlap" + zipbomb (GH-110016) (GH-113913) + +Raise BadZipFile when try to read an entry that overlaps with other entry or +central directory. +(cherry picked from commit 66363b9a7b9fe7c99eba3a185b74c5fdbf842eba) + +Co-authored-by: Serhiy Storchaka +--- + Lib/test/test_zipfile.py | 60 +++++++++++++++++++ + Lib/zipfile.py | 12 ++++ + ...-09-28-13-15-51.gh-issue-109858.43e2dg.rst | 3 + + 3 files changed, 75 insertions(+) + create mode 100644 Misc/NEWS.d/next/Library/2023-09-28-13-15-51.gh-issue-109858.43e2dg.rst + +diff --git a/Lib/test/test_zipfile.py b/Lib/test/test_zipfile.py +index c8e0159765e..9354ab74faa 100644 +--- a/Lib/test/test_zipfile.py ++++ b/Lib/test/test_zipfile.py +@@ -2216,6 +2216,66 @@ def test_decompress_without_3rd_party_library(self): + with zipfile.ZipFile(zip_file) as zf: + self.assertRaises(RuntimeError, zf.extract, 'a.txt') + ++ @requires_zlib() ++ def test_full_overlap(self): ++ data = ( ++ b'PK\x03\x04\x14\x00\x00\x00\x08\x00\xa0lH\x05\xe2\x1e' ++ b'8\xbb\x10\x00\x00\x00\t\x04\x00\x00\x01\x00\x00\x00a\xed' ++ b'\xc0\x81\x08\x00\x00\x00\xc00\xd6\xfbK\\d\x0b`P' ++ b'K\x01\x02\x14\x00\x14\x00\x00\x00\x08\x00\xa0lH\x05\xe2' ++ b'\x1e8\xbb\x10\x00\x00\x00\t\x04\x00\x00\x01\x00\x00\x00\x00' ++ b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00aPK' ++ b'\x01\x02\x14\x00\x14\x00\x00\x00\x08\x00\xa0lH\x05\xe2\x1e' ++ b'8\xbb\x10\x00\x00\x00\t\x04\x00\x00\x01\x00\x00\x00\x00\x00' ++ b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00bPK\x05' ++ b'\x06\x00\x00\x00\x00\x02\x00\x02\x00^\x00\x00\x00/\x00\x00' ++ b'\x00\x00\x00' ++ ) ++ with zipfile.ZipFile(io.BytesIO(data), 'r') as zipf: ++ self.assertEqual(zipf.namelist(), ['a', 'b']) ++ zi = zipf.getinfo('a') ++ self.assertEqual(zi.header_offset, 0) ++ self.assertEqual(zi.compress_size, 16) ++ self.assertEqual(zi.file_size, 1033) ++ zi = zipf.getinfo('b') ++ self.assertEqual(zi.header_offset, 0) ++ self.assertEqual(zi.compress_size, 16) ++ self.assertEqual(zi.file_size, 1033) ++ self.assertEqual(len(zipf.read('a')), 1033) ++ with self.assertRaisesRegex(zipfile.BadZipFile, 'File name.*differ'): ++ zipf.read('b') ++ ++ @requires_zlib() ++ def test_quoted_overlap(self): ++ data = ( ++ b'PK\x03\x04\x14\x00\x00\x00\x08\x00\xa0lH\x05Y\xfc' ++ b'8\x044\x00\x00\x00(\x04\x00\x00\x01\x00\x00\x00a\x00' ++ b'\x1f\x00\xe0\xffPK\x03\x04\x14\x00\x00\x00\x08\x00\xa0l' ++ b'H\x05\xe2\x1e8\xbb\x10\x00\x00\x00\t\x04\x00\x00\x01\x00' ++ b'\x00\x00b\xed\xc0\x81\x08\x00\x00\x00\xc00\xd6\xfbK\\' ++ b'd\x0b`PK\x01\x02\x14\x00\x14\x00\x00\x00\x08\x00\xa0' ++ b'lH\x05Y\xfc8\x044\x00\x00\x00(\x04\x00\x00\x01' ++ b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' ++ b'\x00aPK\x01\x02\x14\x00\x14\x00\x00\x00\x08\x00\xa0l' ++ b'H\x05\xe2\x1e8\xbb\x10\x00\x00\x00\t\x04\x00\x00\x01\x00' ++ b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00$\x00\x00\x00' ++ b'bPK\x05\x06\x00\x00\x00\x00\x02\x00\x02\x00^\x00\x00' ++ b'\x00S\x00\x00\x00\x00\x00' ++ ) ++ with zipfile.ZipFile(io.BytesIO(data), 'r') as zipf: ++ self.assertEqual(zipf.namelist(), ['a', 'b']) ++ zi = zipf.getinfo('a') ++ self.assertEqual(zi.header_offset, 0) ++ self.assertEqual(zi.compress_size, 52) ++ self.assertEqual(zi.file_size, 1064) ++ zi = zipf.getinfo('b') ++ self.assertEqual(zi.header_offset, 36) ++ self.assertEqual(zi.compress_size, 16) ++ self.assertEqual(zi.file_size, 1033) ++ with self.assertRaisesRegex(zipfile.BadZipFile, 'Overlapped entries'): ++ zipf.read('a') ++ self.assertEqual(len(zipf.read('b')), 1033) ++ + def tearDown(self): + unlink(TESTFN) + unlink(TESTFN2) +diff --git a/Lib/zipfile.py b/Lib/zipfile.py +index 6189db5e3e4..058d7163ea1 100644 +--- a/Lib/zipfile.py ++++ b/Lib/zipfile.py +@@ -367,6 +367,7 @@ class ZipInfo (object): + 'compress_size', + 'file_size', + '_raw_time', ++ '_end_offset', + ) + + def __init__(self, filename="NoName", date_time=(1980,1,1,0,0,0)): +@@ -408,6 +409,7 @@ def __init__(self, filename="NoName", date_time=(1980,1,1,0,0,0)): + self.external_attr = 0 # External file attributes + self.compress_size = 0 # Size of the compressed file + self.file_size = 0 # Size of the uncompressed file ++ self._end_offset = None # Start of the next local header or central directory + # Other attributes are set by class ZipFile: + # header_offset Byte offset to the file header + # CRC CRC-32 of the uncompressed file +@@ -1437,6 +1439,12 @@ def _RealGetContents(self): + if self.debug > 2: + print("total", total) + ++ end_offset = self.start_dir ++ for zinfo in sorted(self.filelist, ++ key=lambda zinfo: zinfo.header_offset, ++ reverse=True): ++ zinfo._end_offset = end_offset ++ end_offset = zinfo.header_offset + + def namelist(self): + """Return a list of file names in the archive.""" +@@ -1590,6 +1598,10 @@ def open(self, name, mode="r", pwd=None, *, force_zip64=False): + 'File name in directory %r and header %r differ.' + % (zinfo.orig_filename, fname)) + ++ if (zinfo._end_offset is not None and ++ zef_file.tell() + zinfo.compress_size > zinfo._end_offset): ++ raise BadZipFile(f"Overlapped entries: {zinfo.orig_filename!r} (possible zip bomb)") ++ + # check for encrypted flag & handle password + is_encrypted = zinfo.flag_bits & _MASK_ENCRYPTED + if is_encrypted: +diff --git a/Misc/NEWS.d/next/Library/2023-09-28-13-15-51.gh-issue-109858.43e2dg.rst b/Misc/NEWS.d/next/Library/2023-09-28-13-15-51.gh-issue-109858.43e2dg.rst +new file mode 100644 +index 00000000000..be279caffc4 +--- /dev/null ++++ b/Misc/NEWS.d/next/Library/2023-09-28-13-15-51.gh-issue-109858.43e2dg.rst +@@ -0,0 +1,3 @@ ++Protect :mod:`zipfile` from "quoted-overlap" zipbomb. It now raises ++BadZipFile when try to read an entry that overlaps with other entry or ++central directory. +-- +2.33.0 + diff --git a/backport-3.11-gh-122133-Authenticate-socket-connection-for-so.patch b/backport-CVE-2024-3219-1-gh-122133-Authenticate-socket-connection-for-so.patch similarity index 85% rename from backport-3.11-gh-122133-Authenticate-socket-connection-for-so.patch rename to backport-CVE-2024-3219-1-gh-122133-Authenticate-socket-connection-for-so.patch index ac9452d94af683786eac05736f64a16d8cce6c03..2911f7bdd9f1430ce8a95f0509485f82cd0ed7ed 100644 --- a/backport-3.11-gh-122133-Authenticate-socket-connection-for-so.patch +++ b/backport-CVE-2024-3219-1-gh-122133-Authenticate-socket-connection-for-so.patch @@ -1,21 +1,28 @@ -From 4133aba4f98bd19d2b77c9f01375d795204eef6e Mon Sep 17 00:00:00 2001 -From: yinyongkang -Date: Wed, 4 Sep 2024 16:30:12 +0800 -Subject: [PATCH 1/2] backport 3.11 gh-122133: Authenticate socket connection - for +From 5f90abaa786f994db3907fc31e2ee00ea2cf0929 Mon Sep 17 00:00:00 2001 +From: "Miss Islington (bot)" + <31488909+miss-islington@users.noreply.github.com> +Date: Tue, 30 Jul 2024 14:43:45 +0200 +Subject: [PATCH] [3.11] gh-122133: Authenticate socket connection for + `socket.socketpair()` fallback (GH-122134) (#122426) +Authenticate socket connection for `socket.socketpair()` fallback when the platform does not have a native `socketpair` C API. We authenticate in-process using `getsocketname` and `getpeername` (thanks to Nathaniel J Smith for that suggestion). + +(cherry picked from commit 78df1043dbdce5c989600616f9f87b4ee72944e5) + +Co-authored-by: Seth Michael Larson +Co-authored-by: Gregory P. Smith --- Lib/socket.py | 17 +++ - Lib/test/test_socket.py | 127 +++++++++++++++++- + Lib/test/test_socket.py | 128 +++++++++++++++++- ...-07-22-13-11-28.gh-issue-122133.0mPeta.rst | 5 + - 3 files changed, 147 insertions(+), 2 deletions(-) + 3 files changed, 147 insertions(+), 3 deletions(-) create mode 100644 Misc/NEWS.d/next/Security/2024-07-22-13-11-28.gh-issue-122133.0mPeta.rst diff --git a/Lib/socket.py b/Lib/socket.py -index b5d46eb..d8abf56 100644 +index a0567b76bcf..591d4739a64 100644 --- a/Lib/socket.py +++ b/Lib/socket.py -@@ -648,6 +648,23 @@ else: +@@ -648,6 +648,23 @@ def socketpair(family=AF_INET, type=SOCK_STREAM, proto=0): raise finally: lsock.close() @@ -40,10 +47,10 @@ index b5d46eb..d8abf56 100644 __all__.append("socketpair") diff --git a/Lib/test/test_socket.py b/Lib/test/test_socket.py -index af0d2a4..b554867 100644 +index 42adc573ecc..a60eb436c7b 100644 --- a/Lib/test/test_socket.py +++ b/Lib/test/test_socket.py -@@ -557,19 +557,28 @@ class SocketPairTest(unittest.TestCase, ThreadableTest): +@@ -542,19 +542,27 @@ class SocketPairTest(unittest.TestCase, ThreadableTest): def __init__(self, methodName='runTest'): unittest.TestCase.__init__(self, methodName=methodName) ThreadableTest.__init__(self) @@ -59,7 +66,7 @@ index af0d2a4..b554867 100644 + self.serv, self.cli = self.socketpair() def tearDown(self): - self.serv.close() +- self.serv.close() + if self.serv: + self.serv.close() self.serv = None @@ -74,7 +81,7 @@ index af0d2a4..b554867 100644 self.cli = None ThreadableTest.clientTearDown(self) -@@ -4671,6 +4680,120 @@ class BasicSocketPairTest(SocketPairTest): +@@ -4667,6 +4675,120 @@ def _testSend(self): self.assertEqual(msg, MSG) @@ -197,7 +204,7 @@ index af0d2a4..b554867 100644 def __init__(self, methodName='runTest'): diff --git a/Misc/NEWS.d/next/Security/2024-07-22-13-11-28.gh-issue-122133.0mPeta.rst b/Misc/NEWS.d/next/Security/2024-07-22-13-11-28.gh-issue-122133.0mPeta.rst new file mode 100644 -index 0000000..3544eb3 +index 00000000000..3544eb3824d --- /dev/null +++ b/Misc/NEWS.d/next/Security/2024-07-22-13-11-28.gh-issue-122133.0mPeta.rst @@ -0,0 +1,5 @@ @@ -207,5 +214,5 @@ index 0000000..3544eb3 +Patch by Gregory P. Smith and Seth Larson . Reported by Ellie + -- -2.43.0 +2.33.0 diff --git a/backport-3.11-gh-122133-Rework-pure-Python-socketpair-tests-t.patch b/backport-CVE-2024-3219-2-gh-122133-Rework-pure-Python-socketpair-tests-t.patch similarity index 90% rename from backport-3.11-gh-122133-Rework-pure-Python-socketpair-tests-t.patch rename to backport-CVE-2024-3219-2-gh-122133-Rework-pure-Python-socketpair-tests-t.patch index 9a1333aff12bc74d1d75749eb9166f8c330615a2..3c696cdb41fc264e2212eeb94cfcbb97ce4e8cff 100644 --- a/backport-3.11-gh-122133-Rework-pure-Python-socketpair-tests-t.patch +++ b/backport-CVE-2024-3219-2-gh-122133-Rework-pure-Python-socketpair-tests-t.patch @@ -1,19 +1,24 @@ -From af48af9d3a93f5d6f68eae0db5a51605a18b24e7 Mon Sep 17 00:00:00 2001 -From: yinyongkang -Date: Wed, 4 Sep 2024 16:34:54 +0800 -Subject: [PATCH 2/2] backport 3.11 gh-122133: Rework pure Python socketpair - tests to avoid use +From c5655aa6ad120d2ed7f255bebd6e8b71a9c07dde Mon Sep 17 00:00:00 2001 +From: "Miss Islington (bot)" + <31488909+miss-islington@users.noreply.github.com> +Date: Fri, 2 Aug 2024 15:09:45 +0200 +Subject: [PATCH] [3.11] gh-122133: Rework pure Python socketpair tests to + avoid use of importlib.reload. (GH-122493) (GH-122506) +(cherry picked from commit f071f01b7b7e19d7d6b3a4b0ec62f820ecb14660) + +Co-authored-by: Russell Keith-Magee +Co-authored-by: Gregory P. Smith --- Lib/socket.py | 121 +++++++++++++++++++--------------------- Lib/test/test_socket.py | 20 ++----- 2 files changed, 64 insertions(+), 77 deletions(-) diff --git a/Lib/socket.py b/Lib/socket.py -index d8abf56..7625bb2 100644 +index 591d4739a64..f386241abfb 100644 --- a/Lib/socket.py +++ b/Lib/socket.py -@@ -590,16 +590,65 @@ if hasattr(_socket.socket, "share"): +@@ -590,16 +590,65 @@ def fromshare(info): return socket(0, 0, 0, info) __all__.append("fromshare") @@ -87,7 +92,7 @@ index d8abf56..7625bb2 100644 if family is None: try: family = AF_UNIX -@@ -611,61 +660,7 @@ if hasattr(_socket, "socketpair"): +@@ -611,61 +660,7 @@ def socketpair(family=None, type=SOCK_STREAM, proto=0): return a, b else: @@ -151,10 +156,10 @@ index d8abf56..7625bb2 100644 socketpair.__doc__ = """socketpair([family[, type[, proto]]]) -> (socket object, socket object) diff --git a/Lib/test/test_socket.py b/Lib/test/test_socket.py -index b554867..197dcfa 100644 +index a60eb436c7b..cc803d8753b 100644 --- a/Lib/test/test_socket.py +++ b/Lib/test/test_socket.py -@@ -4681,7 +4681,6 @@ class BasicSocketPairTest(SocketPairTest): +@@ -4676,7 +4676,6 @@ def _testSend(self): class PurePythonSocketPairTest(SocketPairTest): @@ -162,7 +167,7 @@ index b554867..197dcfa 100644 # Explicitly use socketpair AF_INET or AF_INET6 to ensure that is the # code path we're using regardless platform is the pure python one where # `_socket.socketpair` does not exist. (AF_INET does not work with -@@ -4696,28 +4695,21 @@ class PurePythonSocketPairTest(SocketPairTest): +@@ -4691,28 +4690,21 @@ def socketpair(self): # Local imports in this class make for easy security fix backporting. def setUp(self): @@ -198,5 +203,5 @@ index b554867..197dcfa 100644 def test_recv(self): msg = self.serv.recv(1024) -- -2.43.0 +2.33.0 diff --git a/backport-3.11-gh-113171-gh-65056-Fix-private-non-global-IP-ad.patch b/backport-CVE-2024-4032-gh-113171-gh-65056-Fix-private-non-global-IP-ad.patch similarity index 100% rename from backport-3.11-gh-113171-gh-65056-Fix-private-non-global-IP-ad.patch rename to backport-CVE-2024-4032-gh-113171-gh-65056-Fix-private-non-global-IP-ad.patch diff --git a/backport-3.11-gh-121285-Remove-backtracking-when-parsing-tarf.patch b/backport-CVE-2024-6232-gh-121285-Remove-backtracking-when-parsing-tarf.patch similarity index 94% rename from backport-3.11-gh-121285-Remove-backtracking-when-parsing-tarf.patch rename to backport-CVE-2024-6232-gh-121285-Remove-backtracking-when-parsing-tarf.patch index b0aabf11d0e343a012ad271f4ca48bea25c69b52..0e3db4eacdf89a5c64f62dc5ac9bcfc7105c11ad 100644 --- a/backport-3.11-gh-121285-Remove-backtracking-when-parsing-tarf.patch +++ b/backport-CVE-2024-6232-gh-121285-Remove-backtracking-when-parsing-tarf.patch @@ -13,17 +13,17 @@ Subject: [PATCH] [3.11] gh-121285: Remove backtracking when parsing tarfile Co-authored-by: Kirill Podoprigora Co-authored-by: Gregory P. Smith --- - Lib/tarfile.py | 106 +++++++++++------- + Lib/tarfile.py | 105 +++++++++++------- Lib/test/test_tarfile.py | 42 +++++++ ...-07-02-13-39-20.gh-issue-121285.hrl-yI.rst | 2 + - 3 files changed, 112 insertions(+), 38 deletions(-) + 3 files changed, 111 insertions(+), 38 deletions(-) create mode 100644 Misc/NEWS.d/next/Security/2024-07-02-13-39-20.gh-issue-121285.hrl-yI.rst diff --git a/Lib/tarfile.py b/Lib/tarfile.py -index 2808e7e..4d26f05 100755 +index 612217b1ad0..0d6b925533b 100755 --- a/Lib/tarfile.py +++ b/Lib/tarfile.py -@@ -841,6 +841,9 @@ _NAMED_FILTERS = { +@@ -842,6 +842,9 @@ def data_filter(member, dest_path): # Sentinel for replace() defaults, meaning "don't change the attribute" _KEEP = object() @@ -33,7 +33,7 @@ index 2808e7e..4d26f05 100755 class TarInfo(object): """Informational class which holds the details about an archive member given by a tar header block. -@@ -1410,40 +1413,59 @@ class TarInfo(object): +@@ -1411,41 +1414,59 @@ def _proc_pax(self, tarfile): else: pax_headers = tarfile.pax_headers.copy() @@ -81,14 +81,14 @@ index 2808e7e..4d26f05 100755 + raise InvalidHeaderError("invalid header") + if pos + length > len(buf): + raise InvalidHeaderError("invalid header") -+ -+ header_value_end_offset = match.start(1) + length - 1 # Last byte of the header -+ keyword_and_value = buf[match.end(1) + 1:header_value_end_offset] -+ raw_keyword, equals, raw_value = keyword_and_value.partition(b"=") - length, keyword = match.groups() - length = int(length) - if length == 0: ++ header_value_end_offset = match.start(1) + length - 1 # Last byte of the header ++ keyword_and_value = buf[match.end(1) + 1:header_value_end_offset] ++ raw_keyword, equals, raw_value = keyword_and_value.partition(b"=") ++ + # Check the framing of the header. The last character must be '\n' (0x0A) + if not raw_keyword or equals != b"=" or buf[header_value_end_offset] != 0x0A: raise InvalidHeaderError("invalid header") @@ -111,17 +111,17 @@ index 2808e7e..4d26f05 100755 + encoding = "utf-8" + + pos += length -+ + + # If no explicit hdrcharset is set, we use UTF-8 as a default. + if encoding is None: + encoding = "utf-8" + + # After parsing the raw headers we can decode them to text. + for length, raw_keyword, raw_value in raw_headers: - # Normally, we could just use "utf-8" as the encoding and "strict" # as the error handler, but we better not take the risk. For -@@ -1452,17 +1474,16 @@ class TarInfo(object): + # example, GNU tar <= 1.23 is known to store filenames it cannot +@@ -1453,17 +1474,16 @@ def _proc_pax(self, tarfile): # hdrcharset=BINARY header). # We first try the strict standard encoding, and if that fails we # fall back on the user's encoding and error handler. @@ -142,7 +142,7 @@ index 2808e7e..4d26f05 100755 # Fetch the next header. try: -@@ -1477,7 +1498,7 @@ class TarInfo(object): +@@ -1478,7 +1498,7 @@ def _proc_pax(self, tarfile): elif "GNU.sparse.size" in pax_headers: # GNU extended sparse format version 0.0. @@ -151,7 +151,7 @@ index 2808e7e..4d26f05 100755 elif pax_headers.get("GNU.sparse.major") == "1" and pax_headers.get("GNU.sparse.minor") == "0": # GNU extended sparse format version 1.0. -@@ -1499,15 +1520,24 @@ class TarInfo(object): +@@ -1500,15 +1520,24 @@ def _proc_pax(self, tarfile): return next @@ -182,10 +182,10 @@ index 2808e7e..4d26f05 100755 def _proc_gnusparse_01(self, next, pax_headers): diff --git a/Lib/test/test_tarfile.py b/Lib/test/test_tarfile.py -index cad13a9..d473708 100644 +index 389da7be3a3..c99c88ce93a 100644 --- a/Lib/test/test_tarfile.py +++ b/Lib/test/test_tarfile.py -@@ -1183,6 +1183,48 @@ class PaxReadTest(LongnameTest, ReadTest, unittest.TestCase): +@@ -1208,6 +1208,48 @@ def test_pax_number_fields(self): finally: tar.close() @@ -236,12 +236,12 @@ index cad13a9..d473708 100644 # Put all write tests in here that are supposed to be tested diff --git a/Misc/NEWS.d/next/Security/2024-07-02-13-39-20.gh-issue-121285.hrl-yI.rst b/Misc/NEWS.d/next/Security/2024-07-02-13-39-20.gh-issue-121285.hrl-yI.rst new file mode 100644 -index 0000000..81f918b +index 00000000000..81f918bfe2b --- /dev/null +++ b/Misc/NEWS.d/next/Security/2024-07-02-13-39-20.gh-issue-121285.hrl-yI.rst @@ -0,0 +1,2 @@ +Remove backtracking from tarfile header parsing for ``hdrcharset``, PAX, and +GNU sparse headers. -- -2.43.0 +2.33.0 diff --git a/backport-gh-121650-Encode-newlines-in-headers-and-verify-head.patch b/backport-CVE-2024-6923-gh-121650-Encode-newlines-in-headers-and-verify-head.patch similarity index 100% rename from backport-gh-121650-Encode-newlines-in-headers-and-verify-head.patch rename to backport-CVE-2024-6923-gh-121650-Encode-newlines-in-headers-and-verify-head.patch diff --git a/backport-gh-123067-Fix-quadratic-complexity-in-parsing-quoted.patch b/backport-CVE-2024-7592-gh-123067-Fix-quadratic-complexity-in-parsing-quoted.patch similarity index 100% rename from backport-gh-123067-Fix-quadratic-complexity-in-parsing-quoted.patch rename to backport-CVE-2024-7592-gh-123067-Fix-quadratic-complexity-in-parsing-quoted.patch diff --git a/backport-gh-123270-Replaced-SanitizedNames-with-a-more-surgic.patch b/backport-CVE-2024-8088-gh-123270-Replaced-SanitizedNames-with-a-more-surgic.patch similarity index 100% rename from backport-gh-123270-Replaced-SanitizedNames-with-a-more-surgic.patch rename to backport-CVE-2024-8088-gh-123270-Replaced-SanitizedNames-with-a-more-surgic.patch diff --git a/python3.spec b/python3.spec index b0b97fec80feee615e7274f82fb4c3bdb72d66cd..907d7b22b4e3f703bdb03b258e218ce705ad4fe3 100644 --- a/python3.spec +++ b/python3.spec @@ -3,7 +3,7 @@ Summary: Interpreter of the Python3 programming language URL: https://www.python.org/ Version: 3.11.6 -Release: 7 +Release: 8 License: Python-2.0 %global branchversion 3.11 @@ -92,15 +92,17 @@ Source1: pyconfig.h Patch1: 00001-rpath.patch Patch251: 00251-change-user-install-location.patch -Patch6000: backport-3.11-gh-114572-Fix-locking-in-cert_store_stats-and-g.patch -Patch6001: backport-3.11-gh-113171-gh-65056-Fix-private-non-global-IP-ad.patch +Patch6000: backport-CVE-2024-0397-gh-114572-Fix-locking-in-cert_store_stats-and-g.patch +Patch6001: backport-CVE-2024-4032-gh-113171-gh-65056-Fix-private-non-global-IP-ad.patch Patch6002: backport-3.11-gh-115133-Fix-tests-for-XMLPullParser-with-Expa.patch -Patch6003: backport-gh-121650-Encode-newlines-in-headers-and-verify-head.patch -Patch6004: backport-gh-123067-Fix-quadratic-complexity-in-parsing-quoted.patch -Patch6005: backport-gh-123270-Replaced-SanitizedNames-with-a-more-surgic.patch -Patch6006: backport-3.11-gh-121285-Remove-backtracking-when-parsing-tarf.patch -Patch6007: backport-3.11-gh-122133-Authenticate-socket-connection-for-so.patch -Patch6008: backport-3.11-gh-122133-Rework-pure-Python-socketpair-tests-t.patch +Patch6003: backport-CVE-2024-6923-gh-121650-Encode-newlines-in-headers-and-verify-head.patch +Patch6004: backport-CVE-2024-7592-gh-123067-Fix-quadratic-complexity-in-parsing-quoted.patch +Patch6005: backport-CVE-2024-8088-gh-123270-Replaced-SanitizedNames-with-a-more-surgic.patch +Patch6006: backport-CVE-2024-6232-gh-121285-Remove-backtracking-when-parsing-tarf.patch +Patch6007: backport-CVE-2024-3219-1-gh-122133-Authenticate-socket-connection-for-so.patch +Patch6008: backport-CVE-2024-3219-2-gh-122133-Rework-pure-Python-socketpair-tests-t.patch +Patch6009: backport-CVE-2023-6597-gh-91133-tempfile.TemporaryDirectory-fix-symlin.patch +Patch6010: backport-CVE-2024-0450-gh-109858-Protect-zipfile-from-quoted-overlap-z.patch Patch9000: add-the-sm3-method-for-obtaining-the-salt-value.patch Patch9001: 0001-add-loongarch64-support-for-python.patch @@ -209,6 +211,8 @@ rm configure pyconfig.h.in %patch6006 -p1 %patch6007 -p1 %patch6008 -p1 +%patch6009 -p1 +%patch6010 -p1 %patch9000 -p1 %patch9001 -p1 @@ -874,6 +878,18 @@ export BEP_GTDLIST="$BEP_GTDLIST_TMP" %{_mandir}/*/* %changelog +* Tue Sep 24 2024 xinsheng - 3.11.6-8 +- Type:CVE +- CVE:CVE-2024-6232,CVE-2024-3219,CVE-2024-0450,CVE-2023-6597 +- SUG:NA +- DESC:fix CVE-2024-6232,CVE-2024-3219,CVE-2024-0450,CVE-2023-6597 + - rename all CVE patch name + - CVE-2024-6232: Remove backtracking when parsing tarfile headers + - CVE-2024-3219: patch1 Authenticate socket connection for `socket.socketpair()` fallback + - CVE-2024-3219: patch2 Rework pure Python socketpair tests to avoid use of importlib.reload. + - CVE-2024-0450: Protect zipfile from "quoted-overlap" zipbomb + - CVE-2023-6597: tempfile.TemporaryDirectory: fix symlink bug in cleanup + * Wed Sep 04 2024 yinyongkang - 3.11.6-7 - Type:CVE - ID:CVE-2024-6232,CVE-2024-3219