From patchwork Thu Sep 5 18:14:34 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Hugo Simeliere X-Patchwork-Id: 48705 X-Patchwork-Delegate: steve@sakoman.com Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 9E362CE7A81 for ; Thu, 5 Sep 2024 18:15:59 +0000 (UTC) Received: from EUR05-AM6-obe.outbound.protection.outlook.com (EUR05-AM6-obe.outbound.protection.outlook.com [40.107.22.128]) by mx.groups.io with SMTP id smtpd.web11.16770.1725560156617665000 for ; Thu, 05 Sep 2024 11:15:57 -0700 Authentication-Results: mx.groups.io; dkim=fail reason="dkim: body hash did not verify" header.i=@witekio.com header.s=selector2 header.b=aSyzyf48; spf=pass (domain: witekio.com, ip: 40.107.22.128, mailfrom: hsimeliere@witekio.com) ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=P0X/CoDhVic8tme98qMVljDwPdwVY28No3VExA6eodqEIP39+D6kJwzllHY9hCUjg6xda9ikaNAGaY95In0v/jWqrsUrNpsy4ryeAjJGAV58UHrsXfRAYmGxdBLbZWuEQHeuD23pyNhmkmz5n/jBsn6l6J64u1SiGcAh+GTD29yaeF0HVM11NblsiZOUgnOYuMl7WU/6Y1xTkCi8mPCKKtCVdM4CAEeVPtQB+XdPJ3D4C6mTl7SfeN644IDr8R3wpLGcWY3aR9WnaMi/FPQ/Pd5xB272S2y92j20+mwrUJzvk5ei/kvgr/2nCpSzJAF24liPp8ISPd2VcdHfJd4HVA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=2xNK4OeE0AsW88Cyqnx0XmgCU4yg5EbncAJLWJowEFk=; b=mX+IJETggNeX/ET2l06azFaHKoDnRy0kwRSCNxpMKwJYCvBZwxC49dflTufEonz//fYYpIDofMKeoeHZr/vXVEqWkYKs1bKMjk4yLOUJ7CaPyEMdr+/YCkzMwKuKIf8lubOa8sFI+hGc1iUdJKCyDR9nwNYPcydaY0rcNHSRPyIOrhROFt5S+4CM5GJWX2a8UUxGy7/w+4UVkpyxBVPTQQKNq94chgRH5r5zu831i8k7I13QsEV0bhbEH/CuTDtpeGhyHA4TO/cfirLE3+njx9+K1RFGduSmnqBXZfJN1w/rhuwnGX+hxCQWlcTskxH3vOafkkpgvqTKY+a3JzrCrQ== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass smtp.mailfrom=witekio.com; dmarc=pass action=none header.from=witekio.com; dkim=pass header.d=witekio.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=witekio.com; s=selector2; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=2xNK4OeE0AsW88Cyqnx0XmgCU4yg5EbncAJLWJowEFk=; b=aSyzyf48EXka7rjGjvDTF9al2bOklVu6FqIkyEWv3Pyg3/8J1CSIkDvyaE0ijBqurLkty3pyBDAiEIbrWtSrAYRPhdwSoSwx2ZfqTrO9jGO1PVGKSrSx1o4rwXl9X1JI5xIvlaOZ/ufE5Xtw+6jhenkF4PbFqa5BfwVzvCvxRByLffR3JYFtT9137NKDIcCy3+LcrYAN1X4pfbgiE0v1JqN1FpbmXRLPPC0eBqHLZIlUjxW1f1thmGioC37xJq34wPkmStFh5jNZpw/0o20UkPrynhR8Jqbh2u9ZgcgS4TpSAuECZDfOSZ3XPneVAf9CNvGhuXXEwUm+jxlPA+GY6w== Authentication-Results: dkim=none (message not signed) header.d=none;dmarc=none action=none header.from=witekio.com; Received: from PR3P192MB0714.EURP192.PROD.OUTLOOK.COM (2603:10a6:102:48::10) by PAWP192MB2412.EURP192.PROD.OUTLOOK.COM (2603:10a6:102:46d::11) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7918.27; Thu, 5 Sep 2024 18:15:46 +0000 Received: from PR3P192MB0714.EURP192.PROD.OUTLOOK.COM ([fe80::345f:a9e9:d884:3091]) by PR3P192MB0714.EURP192.PROD.OUTLOOK.COM ([fe80::345f:a9e9:d884:3091%5]) with mapi id 15.20.7918.024; Thu, 5 Sep 2024 18:15:45 +0000 From: hsimeliere.opensource@witekio.com To: openembedded-core@lists.openembedded.org CC: Hugo SIMELIERE Subject: [kirkstone][PATCH] python3: CVE-2024-6232 CVE-2024-7592 fixes Date: Thu, 5 Sep 2024 20:14:34 +0200 Message-ID: <20240905181434.6454-1-hsimeliere.opensource@witekio.com> X-Mailer: git-send-email 2.43.0 X-ClientProxiedBy: PAZP264CA0074.FRAP264.PROD.OUTLOOK.COM (2603:10a6:102:1fa::9) To PR3P192MB0714.EURP192.PROD.OUTLOOK.COM (2603:10a6:102:48::10) MIME-Version: 1.0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: PR3P192MB0714:EE_|PAWP192MB2412:EE_ X-MS-Office365-Filtering-Correlation-Id: fba4ade2-ddb2-4d45-1362-08dccdd6c24f X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0;ARA:13230040|376014|1800799024|366016|52116014|38350700014; X-Microsoft-Antispam-Message-Info: 7s11bKURheHkA7AfFzT1iYTqTT/2M8SrERnZCu4gEdVmTdu3acxQVVU36QPYCFrzytqK9xzWwXXRE3DfZEdUlN1/fc1KBB3Blg30yTzsY9D/bjDJ+7v4BD19ocgOmu6+5971OzPd/sDDDjpkXsR2ztS9TxfcEm+9cbVgQUjrQeX4NKi19cRwJCpcyvG0KmzRq+7rBOeFdztut3HsKVVPjrZce4S1t0SCJwveGgQY7vWAR3i5dZJC+8+ckhMS0j3y+VwQDGyq171WH9iF0ycRDfZRHWReWll+JvGSZNMotSSofae/lZqCpSwxA5ZTyFy0RFk9PCnGUsJeR3RzHFQGlPFMYTyGSzxWL+SZtkLf/B66F3neBC8TLfm88h05K08gpE9xgqV1s9Cw7hwOpr0B/d5fdKHlMyM4ymZkA++ENPJvbF9SBz+U0AG6ZL7jAI+MdsI59hrzl+lY27Qw01XhYj8xmJ5mLq6FR+Ye5Y8Hvf0YFaXw2UENlKnnU5QNZZ4Ea4QxUve7OmKOBBj/wKMRqBE9zEGInRlBrDc5t0tYzscRuL1DpyJR682+O/1E9wLK9Tip5va/xy8jinfh9T+7BBnHOlPLKPRJIdS2OH5mlY17wo4FcWdIPe3fCzDEFpLXVNDhrE/NKvXo+nqZf1+89yaFX137tJ4AI91poa049+Q34EIooVT+MxkJR7PtLhs22WiKOXHOnoFaJfXlOH/llDj3aNLYnTZU7Jb24tsBcdwxPtBtuawMCRgIaHp+9CkgeZNH04OXROaEbmti5wWhamTKiCtXqvflBy6EZ1aMLlYNvHAu/w7KTTj9kusl+yp0TP1OsjYMcfutI3rp7gCQTlbga8NwaIwiAbfB4RvOVAfevYiH+0c7gmoZZboGI+M6F0mkM49OJi73C9SS3qQ3sH9c6U1zZqcdBgIUN2QmH1hsaDcPDBgjVI0tT32VD71eF+eGAA/v8xA4N0k/VYl9l1TPc/3kA948c5uZo69g6lZpv89L60CWF8/i+gqLo6zKw/PIbCnLRaM1QxAfkwJ22FbKUzu7b18QZ0OMQG4XzElNoex6ec9riPowB1nPTFFdDTSBVMbpLoAcwSMwkq78TngtzKOEsSeRFhmllTcuqaM4S55C6UzDnFruK05ppdI+lcFzDvxkJnAXjghJr8L9VuKmoUziES/UDFStj6T0ecIRvry6uEpnFZnVrtmzb6pWkWLHwAT6nNCmwUJaikHNSNl8tCjKREUcE+Q840+TAitrM2QLku2tT8BHVfJYZ1Ng+2Vqp2Uut6KOgtExiWDDLFL8eeGpJ3MmljPK3UAG8QRxyEkfLiShkSXc6N22AV8U+lWIi5SyH6jdpNTSjIx+JYTRqxIWboQ68TokU9Fx82w= X-Forefront-Antispam-Report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:PR3P192MB0714.EURP192.PROD.OUTLOOK.COM;PTR:;CAT:NONE;SFS:(13230040)(376014)(1800799024)(366016)(52116014)(38350700014);DIR:OUT;SFP:1102; X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: JUBFXBmtVnYNIqiliI3JgSrqHnwNPyvQLBToIazCxEjplde73xTqVPqF/4M1QsBDCR9rxZ3Hf71KGQiHJQb1LhHD7QwlUBffsCSpSg9XoWaR/wQWMh8ktnDIigN/gCt6FKLZ/6uSFsb2IgIFAlp+B+thLDcVvSpttkMPAr6yWn/t51/DUG9fda7bOewddpYYRQh9oAVInl/O2tlr7M4t1zR89neMQKuCy5PKATSujlRr/VaMHU3bS135basd3UZTXvtpanylENG1GdgueVEk9f8slJ2VoJBsWRoUuxB2/ykKQ1uWQ/Uv2TLHpJvAuhQmJir/CZENM2N9oxITx1rlglomBFbpvXUOaizg3Sqfsk3DnrssSUzGKstLJTxR/B+9FF+9AQ/7Ep95lhIEbZYuOemAM6nGFhg9SrAvbnISjIQY4Ns2FGdKb85oLc+G4AZO5B1zCRvB2WSUGIqRa96JEvv5RS/XbDcQk0kCnzhzqA61Jx5h9zryybzdPDJR09JBRAS96XfMYPyvMhuLXzgUpcsPjQgEcYy2s9AruU3Q0hoxJc6JoIVfnhnsQicaIi8JCR8Z0uQEQlDXqwKTnNrxW/rJcQu9gA0yyv/BwVqk2MTiQPNvc984vGBsMmLZZji3JoqzCmbWI0h525SCWE1zypVaNxkWQsWLrWqoHz6YOFV36BAXa9EBrGfXMrfv3mm5SWrSMDJDuFyqKkurZDo3EuGbCMsFtncus7XufGAOCGfqrilbji427p1jJ53SdB2OVHBGk3UuV2+y2QNzX+9VOf3k6OubQneCyTDEMXxyMDVFngHPvpgb0SB5aSzgs3xfFqo1EE3M6OGwa80EDRd5sAPkmUm9kvFlpvSit8hbW8wGv4fxKgHnTFhxBahQ6kP6n8AnZfeBx2dTBMjBgkubeFjxEsxTNTUuNYeXFZ3ld5DdLa8KIQaaek6jWibm/OxqaCAy7N5zBo/Lp6g53GJOAGkUxrnfR/1+46g2V5ScGLglo+G4Roga2s3etMbBj+euvX+Q6r+ezGe5RJWCnjH01YlIcseFJ9eCcQ8oD469EVbwlQUrJuvuC0REDhwnjXYas0rZH5iDohGX/dSp98sZDwDfcFffHzsut/JsOu62U6rca/LUJ4jkh8bPPgSWvRDjaJI2IIB/EdCyUA9z0e0420iEZBIdR72NbjMxVoo8bSaLPTZahBCjx/o/kJMGdUzJqcE7tLK9z0b6z+mbiZ+pRr6mX+44Ka223UuE4QZN6vjKFA7O83Ld0kFKSh6CilQdKfiVixcx5bkLzNW7WUErin/GVsFcOqzkhl3F+i9wsGhWJPDo/2E12Y3rVRstvm4JVeG2sjJsVKtQlVKBlecr2OPXLRS9ugvqOeUNCnMqOM89hUoxdnpn22C5RGo1f+l7uaBrAxkaR5AB6JyJH1JQjz4UnByRxV3w1EDsLHTMXZHJ9iGPyBLNks3bP+NCi6KBpylLdsTuoeKkX9CoK1i4aJi/ZDTWbR7lHkTkRmsN26FrAyBGZRTFX3kre9F5xdsuMarW35yYK7mD89yLxXGRHkfQZUzqqg5CdZMm2suqNJh3juHASRW/3TWAVIv3uUTntHzDiOyaFhxcO+UDnf4n5Q== X-OriginatorOrg: witekio.com X-MS-Exchange-CrossTenant-Network-Message-Id: fba4ade2-ddb2-4d45-1362-08dccdd6c24f X-MS-Exchange-CrossTenant-AuthSource: PR3P192MB0714.EURP192.PROD.OUTLOOK.COM X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 05 Sep 2024 18:15:45.7329 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 317e086a-301a-49af-9ea4-48a1c458b903 X-MS-Exchange-CrossTenant-MailboxType: HOSTED X-MS-Exchange-CrossTenant-UserPrincipalName: HgtaxvXVKuR/KsqLC5934W882LX2s8Q2C6hPfXqeQcM3/H0hN15n3CL16bwz8A/ucx7N6URZpahPEq/Dwjvjbw== X-MS-Exchange-Transport-CrossTenantHeadersStamped: PAWP192MB2412 List-Id: X-Webhook-Received: from li982-79.members.linode.com [45.33.32.79] by aws-us-west-2-korg-lkml-1.web.codeaurora.org with HTTPS for ; Thu, 05 Sep 2024 18:15:59 -0000 X-Groupsio-URL: https://lists.openembedded.org/g/openembedded-core/message/204242 From: Hugo SIMELIERE Upstream-Status: Backport from https://github.com/python/cpython/commit/b2f11ca7667e4d57c71c1c88b255115f16042d9a Upstream-Status: Backport from https://github.com/python/cpython/commit/743acbe872485dc18df4d8ab2dc7895187f062c4 Signed-off-by: Hugo SIMELIERE --- .../python/python3/CVE-2024-6232.patch | 251 ++++++++++++++++++ .../python/python3/CVE-2024-7592.patch | 140 ++++++++++ .../python/python3_3.10.14.bb | 2 + 3 files changed, 393 insertions(+) create mode 100644 meta/recipes-devtools/python/python3/CVE-2024-6232.patch create mode 100644 meta/recipes-devtools/python/python3/CVE-2024-7592.patch diff --git a/meta/recipes-devtools/python/python3/CVE-2024-6232.patch b/meta/recipes-devtools/python/python3/CVE-2024-6232.patch new file mode 100644 index 0000000000..874cbfe40c --- /dev/null +++ b/meta/recipes-devtools/python/python3/CVE-2024-6232.patch @@ -0,0 +1,251 @@ +From 3a22dc1079be5a75750d24dc6992956e7b84b5a0 Mon Sep 17 00:00:00 2001 +From: Seth Michael Larson +Date: Tue, 3 Sep 2024 10:07:53 -0500 +Subject: [PATCH 2/2] [3.10] gh-121285: Remove backtracking when parsing + tarfile headers (GH-121286) (#123640) + +* Remove backtracking when parsing tarfile headers +* Rewrite PAX header parsing to be stricter +* Optimize parsing of GNU extended sparse headers v0.0 + +(cherry picked from commit 34ddb64d088dd7ccc321f6103d23153256caa5d4) + +Upstream-Status: Backport from https://github.com/python/cpython/commit/743acbe872485dc18df4d8ab2dc7895187f062c4 +CVE: CVE-2024-6232 + +Co-authored-by: Kirill Podoprigora +Co-authored-by: Gregory P. Smith +Signed-off-by: Hugo SIMELIERE +--- + 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, 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 495349f08f9..3ab6811d633 100755 +--- a/Lib/tarfile.py ++++ b/Lib/tarfile.py +@@ -841,6 +841,9 @@ def data_filter(member, dest_path): + # Sentinel for replace() defaults, meaning "don't change the attribute" + _KEEP = object() + ++# Header length is digits followed by a space. ++_header_length_prefix_re = re.compile(br"([0-9]{1,20}) ") ++ + class TarInfo(object): + """Informational class which holds the details about an + archive member given by a tar header block. +@@ -1410,41 +1413,59 @@ def _proc_pax(self, tarfile): + else: + pax_headers = tarfile.pax_headers.copy() + +- # Check if the pax header contains a hdrcharset field. This tells us +- # the encoding of the path, linkpath, uname and gname fields. Normally, +- # these fields are UTF-8 encoded but since POSIX.1-2008 tar +- # implementations are allowed to store them as raw binary strings if +- # the translation to UTF-8 fails. +- match = re.search(br"\d+ hdrcharset=([^\n]+)\n", buf) +- if match is not None: +- pax_headers["hdrcharset"] = match.group(1).decode("utf-8") +- +- # For the time being, we don't care about anything other than "BINARY". +- # The only other value that is currently allowed by the standard is +- # "ISO-IR 10646 2000 UTF-8" in other words UTF-8. +- hdrcharset = pax_headers.get("hdrcharset") +- if hdrcharset == "BINARY": +- encoding = tarfile.encoding +- else: +- encoding = "utf-8" +- + # Parse pax header information. A record looks like that: + # "%d %s=%s\n" % (length, keyword, value). length is the size + # of the complete record including the length field itself and +- # the newline. keyword and value are both UTF-8 encoded strings. +- regex = re.compile(br"(\d+) ([^=]+)=") ++ # the newline. + pos = 0 +- while True: +- match = regex.match(buf, pos) +- if not match: +- break ++ encoding = None ++ raw_headers = [] ++ while len(buf) > pos and buf[pos] != 0x00: ++ if not (match := _header_length_prefix_re.match(buf, pos)): ++ raise InvalidHeaderError("invalid header") ++ try: ++ length = int(match.group(1)) ++ except ValueError: ++ raise InvalidHeaderError("invalid header") ++ # Headers must be at least 5 bytes, shortest being '5 x=\n'. ++ # Value is allowed to be empty. ++ if length < 5: ++ raise InvalidHeaderError("invalid header") ++ if pos + length > len(buf): ++ raise InvalidHeaderError("invalid header") + +- 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") +- value = buf[match.end(2) + 1:match.start(1) + length - 1] ++ raw_headers.append((length, raw_keyword, raw_value)) ++ ++ # Check if the pax header contains a hdrcharset field. This tells us ++ # the encoding of the path, linkpath, uname and gname fields. Normally, ++ # these fields are UTF-8 encoded but since POSIX.1-2008 tar ++ # implementations are allowed to store them as raw binary strings if ++ # the translation to UTF-8 fails. For the time being, we don't care about ++ # anything other than "BINARY". The only other value that is currently ++ # allowed by the standard is "ISO-IR 10646 2000 UTF-8" in other words UTF-8. ++ # Note that we only follow the initial 'hdrcharset' setting to preserve ++ # the initial behavior of the 'tarfile' module. ++ if raw_keyword == b"hdrcharset" and encoding is None: ++ if raw_value == b"BINARY": ++ encoding = tarfile.encoding ++ else: # This branch ensures only the first 'hdrcharset' header is used. ++ 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 + # example, GNU tar <= 1.23 is known to store filenames it cannot +@@ -1452,17 +1473,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. +- keyword = self._decode_pax_field(keyword, "utf-8", "utf-8", ++ keyword = self._decode_pax_field(raw_keyword, "utf-8", "utf-8", + tarfile.errors) + if keyword in PAX_NAME_FIELDS: +- value = self._decode_pax_field(value, encoding, tarfile.encoding, ++ value = self._decode_pax_field(raw_value, encoding, tarfile.encoding, + tarfile.errors) + else: +- value = self._decode_pax_field(value, "utf-8", "utf-8", ++ value = self._decode_pax_field(raw_value, "utf-8", "utf-8", + tarfile.errors) + + pax_headers[keyword] = value +- pos += length + + # Fetch the next header. + try: +@@ -1477,7 +1497,7 @@ def _proc_pax(self, tarfile): + + elif "GNU.sparse.size" in pax_headers: + # GNU extended sparse format version 0.0. +- self._proc_gnusparse_00(next, pax_headers, buf) ++ self._proc_gnusparse_00(next, raw_headers) + + 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 +1519,24 @@ def _proc_pax(self, tarfile): + + return next + +- def _proc_gnusparse_00(self, next, pax_headers, buf): ++ def _proc_gnusparse_00(self, next, raw_headers): + """Process a GNU tar extended sparse header, version 0.0. + """ + offsets = [] +- for match in re.finditer(br"\d+ GNU.sparse.offset=(\d+)\n", buf): +- offsets.append(int(match.group(1))) + numbytes = [] +- for match in re.finditer(br"\d+ GNU.sparse.numbytes=(\d+)\n", buf): +- numbytes.append(int(match.group(1))) ++ for _, keyword, value in raw_headers: ++ if keyword == b"GNU.sparse.offset": ++ try: ++ offsets.append(int(value.decode())) ++ except ValueError: ++ raise InvalidHeaderError("invalid header") ++ ++ elif keyword == b"GNU.sparse.numbytes": ++ try: ++ numbytes.append(int(value.decode())) ++ except ValueError: ++ raise InvalidHeaderError("invalid header") ++ + next.sparse = list(zip(offsets, numbytes)) + + def _proc_gnusparse_01(self, next, pax_headers): +diff --git a/Lib/test/test_tarfile.py b/Lib/test/test_tarfile.py +index cfc13bccb20..007c3e94acb 100644 +--- a/Lib/test/test_tarfile.py ++++ b/Lib/test/test_tarfile.py +@@ -1139,6 +1139,48 @@ def test_pax_number_fields(self): + finally: + tar.close() + ++ def test_pax_header_bad_formats(self): ++ # The fields from the pax header have priority over the ++ # TarInfo. ++ pax_header_replacements = ( ++ b" foo=bar\n", ++ b"0 \n", ++ b"1 \n", ++ b"2 \n", ++ b"3 =\n", ++ b"4 =a\n", ++ b"1000000 foo=bar\n", ++ b"0 foo=bar\n", ++ b"-12 foo=bar\n", ++ b"000000000000000000000000036 foo=bar\n", ++ ) ++ pax_headers = {"foo": "bar"} ++ ++ for replacement in pax_header_replacements: ++ with self.subTest(header=replacement): ++ tar = tarfile.open(tmpname, "w", format=tarfile.PAX_FORMAT, ++ encoding="iso8859-1") ++ try: ++ t = tarfile.TarInfo() ++ t.name = "pax" # non-ASCII ++ t.uid = 1 ++ t.pax_headers = pax_headers ++ tar.addfile(t) ++ finally: ++ tar.close() ++ ++ with open(tmpname, "rb") as f: ++ data = f.read() ++ self.assertIn(b"11 foo=bar\n", data) ++ data = data.replace(b"11 foo=bar\n", replacement) ++ ++ with open(tmpname, "wb") as f: ++ f.truncate() ++ f.write(data) ++ ++ with self.assertRaisesRegex(tarfile.ReadError, r"method tar: ReadError\('invalid header'\)"): ++ tarfile.open(tmpname, encoding="iso8859-1") ++ + + class WriteTestBase(TarTest): + # 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 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.46.0 + diff --git a/meta/recipes-devtools/python/python3/CVE-2024-7592.patch b/meta/recipes-devtools/python/python3/CVE-2024-7592.patch new file mode 100644 index 0000000000..7303a41e20 --- /dev/null +++ b/meta/recipes-devtools/python/python3/CVE-2024-7592.patch @@ -0,0 +1,140 @@ +From 3c15b8437f57fe1027171b34af88bf791cf1868c Mon Sep 17 00:00:00 2001 +From: "Miss Islington (bot)" + <31488909+miss-islington@users.noreply.github.com> +Date: Wed, 4 Sep 2024 17:50:36 +0200 +Subject: [PATCH 1/2] [3.10] gh-123067: Fix quadratic complexity in parsing + "-quoted cookie values with backslashes (GH-123075) (#123106) + +This fixes CVE-2024-7592. +(cherry picked from commit 44e458357fca05ca0ae2658d62c8c595b048b5ef) + +Upstream-Status: Backport from https://github.com/python/cpython/commit/b2f11ca7667e4d57c71c1c88b255115f16042d9a +CVE: CVE-2024-7592 + +Co-authored-by: Serhiy Storchaka +Signed-off-by: Hugo SIMELIERE +--- + Lib/http/cookies.py | 34 ++++------------- + Lib/test/test_http_cookies.py | 38 +++++++++++++++++++ + ...-08-16-19-13-21.gh-issue-123067.Nx9O4R.rst | 1 + + 3 files changed, 47 insertions(+), 26 deletions(-) + create mode 100644 Misc/NEWS.d/next/Library/2024-08-16-19-13-21.gh-issue-123067.Nx9O4R.rst + +diff --git a/Lib/http/cookies.py b/Lib/http/cookies.py +index 35ac2dc6ae2..2c1f021d0ab 100644 +--- a/Lib/http/cookies.py ++++ b/Lib/http/cookies.py +@@ -184,8 +184,13 @@ def _quote(str): + return '"' + str.translate(_Translator) + '"' + + +-_OctalPatt = re.compile(r"\\[0-3][0-7][0-7]") +-_QuotePatt = re.compile(r"[\\].") ++_unquote_sub = re.compile(r'\\(?:([0-3][0-7][0-7])|(.))').sub ++ ++def _unquote_replace(m): ++ if m[1]: ++ return chr(int(m[1], 8)) ++ else: ++ return m[2] + + def _unquote(str): + # If there aren't any doublequotes, +@@ -205,30 +210,7 @@ def _unquote(str): + # \012 --> \n + # \" --> " + # +- i = 0 +- n = len(str) +- res = [] +- while 0 <= i < n: +- o_match = _OctalPatt.search(str, i) +- q_match = _QuotePatt.search(str, i) +- if not o_match and not q_match: # Neither matched +- res.append(str[i:]) +- break +- # else: +- j = k = -1 +- if o_match: +- j = o_match.start(0) +- if q_match: +- k = q_match.start(0) +- if q_match and (not o_match or k < j): # QuotePatt matched +- res.append(str[i:k]) +- res.append(str[k+1]) +- i = k + 2 +- else: # OctalPatt matched +- res.append(str[i:j]) +- res.append(chr(int(str[j+1:j+4], 8))) +- i = j + 4 +- return _nulljoin(res) ++ return _unquote_sub(_unquote_replace, str) + + # The _getdate() routine is used to set the expiration time in the cookie's HTTP + # header. By default, _getdate() returns the current time in the appropriate +diff --git a/Lib/test/test_http_cookies.py b/Lib/test/test_http_cookies.py +index 6072c7e15e9..644e75cd5b7 100644 +--- a/Lib/test/test_http_cookies.py ++++ b/Lib/test/test_http_cookies.py +@@ -5,6 +5,7 @@ + import unittest + from http import cookies + import pickle ++from test import support + + + class CookieTests(unittest.TestCase): +@@ -58,6 +59,43 @@ def test_basic(self): + for k, v in sorted(case['dict'].items()): + self.assertEqual(C[k].value, v) + ++ def test_unquote(self): ++ cases = [ ++ (r'a="b=\""', 'b="'), ++ (r'a="b=\\"', 'b=\\'), ++ (r'a="b=\="', 'b=='), ++ (r'a="b=\n"', 'b=n'), ++ (r'a="b=\042"', 'b="'), ++ (r'a="b=\134"', 'b=\\'), ++ (r'a="b=\377"', 'b=\xff'), ++ (r'a="b=\400"', 'b=400'), ++ (r'a="b=\42"', 'b=42'), ++ (r'a="b=\\042"', 'b=\\042'), ++ (r'a="b=\\134"', 'b=\\134'), ++ (r'a="b=\\\""', 'b=\\"'), ++ (r'a="b=\\\042"', 'b=\\"'), ++ (r'a="b=\134\""', 'b=\\"'), ++ (r'a="b=\134\042"', 'b=\\"'), ++ ] ++ for encoded, decoded in cases: ++ with self.subTest(encoded): ++ C = cookies.SimpleCookie() ++ C.load(encoded) ++ self.assertEqual(C['a'].value, decoded) ++ ++ @support.requires_resource('cpu') ++ def test_unquote_large(self): ++ n = 10**6 ++ for encoded in r'\\', r'\134': ++ with self.subTest(encoded): ++ data = 'a="b=' + encoded*n + ';"' ++ C = cookies.SimpleCookie() ++ C.load(data) ++ value = C['a'].value ++ self.assertEqual(value[:3], 'b=\\') ++ self.assertEqual(value[-2:], '\\;') ++ self.assertEqual(len(value), n + 3) ++ + def test_load(self): + C = cookies.SimpleCookie() + C.load('Customer="WILE_E_COYOTE"; Version=1; Path=/acme') +diff --git a/Misc/NEWS.d/next/Library/2024-08-16-19-13-21.gh-issue-123067.Nx9O4R.rst b/Misc/NEWS.d/next/Library/2024-08-16-19-13-21.gh-issue-123067.Nx9O4R.rst +new file mode 100644 +index 00000000000..6a234561fe3 +--- /dev/null ++++ b/Misc/NEWS.d/next/Library/2024-08-16-19-13-21.gh-issue-123067.Nx9O4R.rst +@@ -0,0 +1 @@ ++Fix quadratic complexity in parsing ``"``-quoted cookie values with backslashes by :mod:`http.cookies`. +-- +2.46.0 + diff --git a/meta/recipes-devtools/python/python3_3.10.14.bb b/meta/recipes-devtools/python/python3_3.10.14.bb index b5bc80ab88..f31644e486 100644 --- a/meta/recipes-devtools/python/python3_3.10.14.bb +++ b/meta/recipes-devtools/python/python3_3.10.14.bb @@ -36,6 +36,8 @@ SRC_URI = "http://www.python.org/ftp/python/${PV}/Python-${PV}.tar.xz \ file://deterministic_imports.patch \ file://0001-Avoid-shebang-overflow-on-python-config.py.patch \ file://0001-test_storlines-skip-due-to-load-variability.patch \ + file://CVE-2024-7592.patch \ + file://CVE-2024-6232.patch \ " SRC_URI:append:class-native = " \