From 38559af9fcddfb624d228cd97c167a2251a74a6d Mon Sep 17 00:00:00 2001 From: xinsheng3 Date: Wed, 10 Jul 2024 11:11:27 +0800 Subject: [PATCH] Fix locking in cert_store_stats and get_ca_certs Fix xml tree assert error Update openssl version for test case --- ...x-locking-in-cert_store_stats-and-ge.patch | 177 ++++++++++++++++++ backport-fix_xml_tree_assert_error.patch | 89 +++++++++ python3.spec | 17 +- update-openssl-version-for-test-case.patch | 25 +++ 4 files changed, 307 insertions(+), 1 deletion(-) create mode 100644 backport-3.9-gh-114572-Fix-locking-in-cert_store_stats-and-ge.patch create mode 100644 backport-fix_xml_tree_assert_error.patch create mode 100644 update-openssl-version-for-test-case.patch diff --git a/backport-3.9-gh-114572-Fix-locking-in-cert_store_stats-and-ge.patch b/backport-3.9-gh-114572-Fix-locking-in-cert_store_stats-and-ge.patch new file mode 100644 index 0000000..0bb6328 --- /dev/null +++ b/backport-3.9-gh-114572-Fix-locking-in-cert_store_stats-and-ge.patch @@ -0,0 +1,177 @@ +From b228655c227b2ca298a8ffac44d14ce3d22f6faa Mon Sep 17 00:00:00 2001 +From: Seth Michael Larson +Date: Fri, 10 May 2024 06:46:12 -0500 +Subject: [PATCH] [3.9] gh-114572: Fix locking in cert_store_stats and + get_ca_certs (#118109) + +--- + ...-04-19-11-21-13.gh-issue-114572.t1QMQD.rst | 4 + + Modules/_ssl.c | 91 ++++++++++++++++++- + 2 files changed, 92 insertions(+), 3 deletions(-) + create mode 100644 Misc/NEWS.d/next/Security/2024-04-19-11-21-13.gh-issue-114572.t1QMQD.rst + +diff --git a/Misc/NEWS.d/next/Security/2024-04-19-11-21-13.gh-issue-114572.t1QMQD.rst b/Misc/NEWS.d/next/Security/2024-04-19-11-21-13.gh-issue-114572.t1QMQD.rst +new file mode 100644 +index 0000000000..b4f9fe64db +--- /dev/null ++++ b/Misc/NEWS.d/next/Security/2024-04-19-11-21-13.gh-issue-114572.t1QMQD.rst +@@ -0,0 +1,4 @@ ++:meth:`ssl.SSLContext.cert_store_stats` and ++:meth:`ssl.SSLContext.get_ca_certs` now correctly lock access to the ++certificate store, when the :class:`ssl.SSLContext` is shared across ++multiple threads. +diff --git a/Modules/_ssl.c b/Modules/_ssl.c +index 3f95d3e103..5e0be34d6f 100644 +--- a/Modules/_ssl.c ++++ b/Modules/_ssl.c +@@ -166,6 +166,10 @@ extern const SSL_METHOD *TLSv1_2_method(void); + # define PY_OPENSSL_1_1_API 1 + #endif + ++#if (OPENSSL_VERSION_NUMBER >= 0x30300000L) && !defined(LIBRESSL_VERSION_NUMBER) ++# define OPENSSL_VERSION_3_3 1 ++#endif ++ + /* SNI support (client- and server-side) appeared in OpenSSL 1.0.0 and 0.9.8f + * This includes the SSL_set_SSL_CTX() function. + */ +@@ -210,6 +214,16 @@ extern const SSL_METHOD *TLSv1_2_method(void); + #define HAVE_OPENSSL_CRYPTO_LOCK + #endif + ++/* OpenSSL 1.1+ allows locking X509_STORE, 1.0.2 doesn't. */ ++#ifdef OPENSSL_VERSION_1_1 ++#define HAVE_OPENSSL_X509_STORE_LOCK ++#endif ++ ++/* OpenSSL 3.3 added the X509_STORE_get1_objects API */ ++#ifdef OPENSSL_VERSION_3_3 ++#define HAVE_OPENSSL_X509_STORE_GET1_OBJECTS 1 ++#endif ++ + #if defined(OPENSSL_VERSION_1_1) && !defined(OPENSSL_NO_SSL2) + #define OPENSSL_NO_SSL2 + #endif +@@ -4675,6 +4689,54 @@ set_sni_callback(PySSLContext *self, PyObject *arg, void *c) + #endif + } + ++/* Shim of X509_STORE_get1_objects API from OpenSSL 3.3 ++ * Only available with the X509_STORE_lock() API */ ++#if defined(HAVE_OPENSSL_X509_STORE_LOCK) && !defined(OPENSSL_VERSION_3_3) ++#define HAVE_OPENSSL_X509_STORE_GET1_OBJECTS 1 ++ ++static X509_OBJECT *x509_object_dup(const X509_OBJECT *obj) ++{ ++ int ok; ++ X509_OBJECT *ret = X509_OBJECT_new(); ++ if (ret == NULL) { ++ return NULL; ++ } ++ switch (X509_OBJECT_get_type(obj)) { ++ case X509_LU_X509: ++ ok = X509_OBJECT_set1_X509(ret, X509_OBJECT_get0_X509(obj)); ++ break; ++ case X509_LU_CRL: ++ /* X509_OBJECT_get0_X509_CRL was not const-correct prior to 3.0.*/ ++ ok = X509_OBJECT_set1_X509_CRL( ++ ret, X509_OBJECT_get0_X509_CRL((X509_OBJECT *)obj)); ++ break; ++ default: ++ /* We cannot duplicate unrecognized types in a polyfill, but it is ++ * safe to leave an empty object. The caller will ignore it. */ ++ ok = 1; ++ break; ++ } ++ if (!ok) { ++ X509_OBJECT_free(ret); ++ return NULL; ++ } ++ return ret; ++} ++ ++static STACK_OF(X509_OBJECT) * ++X509_STORE_get1_objects(X509_STORE *store) ++{ ++ STACK_OF(X509_OBJECT) *ret; ++ if (!X509_STORE_lock(store)) { ++ return NULL; ++ } ++ ret = sk_X509_OBJECT_deep_copy(X509_STORE_get0_objects(store), ++ x509_object_dup, X509_OBJECT_free); ++ X509_STORE_unlock(store); ++ return ret; ++} ++#endif ++ + PyDoc_STRVAR(PySSLContext_sni_callback_doc, + "Set a callback that will be called when a server name is provided by the SSL/TLS client in the SNI extension.\n\ + \n\ +@@ -4704,7 +4766,15 @@ _ssl__SSLContext_cert_store_stats_impl(PySSLContext *self) + int x509 = 0, crl = 0, ca = 0, i; + + store = SSL_CTX_get_cert_store(self->ctx); ++#if HAVE_OPENSSL_X509_STORE_GET1_OBJECTS ++ objs = X509_STORE_get1_objects(store); ++ if (objs == NULL) { ++ PyErr_SetString(PyExc_MemoryError, "failed to query cert store"); ++ return NULL; ++ } ++#else + objs = X509_STORE_get0_objects(store); ++#endif + for (i = 0; i < sk_X509_OBJECT_num(objs); i++) { + obj = sk_X509_OBJECT_value(objs, i); + switch (X509_OBJECT_get_type(obj)) { +@@ -4718,12 +4788,13 @@ _ssl__SSLContext_cert_store_stats_impl(PySSLContext *self) + crl++; + break; + default: +- /* Ignore X509_LU_FAIL, X509_LU_RETRY, X509_LU_PKEY. +- * As far as I can tell they are internal states and never +- * stored in a cert store */ ++ /* Ignore unrecognized types. */ + break; + } + } ++#if HAVE_OPENSSL_X509_STORE_GET1_OBJECTS ++ sk_X509_OBJECT_pop_free(objs, X509_OBJECT_free); ++#endif + return Py_BuildValue("{sisisi}", "x509", x509, "crl", crl, + "x509_ca", ca); + } +@@ -4755,7 +4826,15 @@ _ssl__SSLContext_get_ca_certs_impl(PySSLContext *self, int binary_form) + } + + store = SSL_CTX_get_cert_store(self->ctx); ++#if HAVE_OPENSSL_X509_STORE_GET1_OBJECTS ++ objs = X509_STORE_get1_objects(store); ++ if (objs == NULL) { ++ PyErr_SetString(PyExc_MemoryError, "failed to query cert store"); ++ return NULL; ++ } ++#else + objs = X509_STORE_get0_objects(store); ++#endif + for (i = 0; i < sk_X509_OBJECT_num(objs); i++) { + X509_OBJECT *obj; + X509 *cert; +@@ -4783,9 +4862,15 @@ _ssl__SSLContext_get_ca_certs_impl(PySSLContext *self, int binary_form) + } + Py_CLEAR(ci); + } ++#if HAVE_OPENSSL_X509_STORE_GET1_OBJECTS ++ sk_X509_OBJECT_pop_free(objs, X509_OBJECT_free); ++#endif + return rlist; + + error: ++#if HAVE_OPENSSL_X509_STORE_GET1_OBJECTS ++ sk_X509_OBJECT_pop_free(objs, X509_OBJECT_free); ++#endif + Py_XDECREF(ci); + Py_XDECREF(rlist); + return NULL; +-- +2.21.0.windows.1 + diff --git a/backport-fix_xml_tree_assert_error.patch b/backport-fix_xml_tree_assert_error.patch new file mode 100644 index 0000000..dd35a76 --- /dev/null +++ b/backport-fix_xml_tree_assert_error.patch @@ -0,0 +1,89 @@ +From 4a08e7b3431cd32a0daf22a33421cd3035343dc4 Mon Sep 17 00:00:00 2001 +From: Serhiy Storchaka +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. + +Other adaptation: +For the expat version number, whether a feature exists in the header file is used to determine whether to execute a test case. + +diff --git a/Lib/test/test_xml_etree.py b/Lib/test/test_xml_etree.py +index 142ce2c..a8d5c2d 100644 +--- a/Lib/test/test_xml_etree.py ++++ b/Lib/test/test_xml_etree.py +@@ -14,6 +14,8 @@ import locale + import operator + import os + import pickle ++import pyexpat ++import subprocess + import sys + import textwrap + import types +@@ -96,6 +98,11 @@ ENTITY_XML = """\ + &entity; + """ + ++macro_to_find = 'XML_SetReparseDeferralEnabled' ++header_file = '/usr/include/expat.h' ++result = subprocess.run(['grep', '-q', macro_to_find, header_file], stdout=subprocess.PIPE, stderr=subprocess.PIPE) ++fails_with_expat = (unittest.expectedFailure if result.returncode == 0 else lambda test: test) ++ + EXTERNAL_ENTITY_XML = """\ + +@@ -1410,27 +1417,38 @@ class XMLPullParserTest(unittest.TestCase): + with self.assertRaises(StopIteration): + next(it) + +- def test_simple_xml_with_ns(self): ++ def test_simple_xml(self, chunk_size=None): + parser = ET.XMLPullParser() + self.assert_event_tags(parser, []) +- self._feed(parser, "\n") +- self.assert_event_tags(parser, []) +- self._feed(parser, "\n") ++ self._feed(parser, "\n", chunk_size) + self.assert_event_tags(parser, []) +- self._feed(parser, "text\n text\n") +- self.assert_event_tags(parser, [('end', '{namespace}element')]) +- self._feed(parser, "texttail\n") +- self._feed(parser, "\n") ++ self._feed(parser, ">\n", chunk_size) ++ self.assert_event_tags(parser, [('end', 'element')]) ++ self._feed(parser, "texttail\n", chunk_size) ++ self._feed(parser, "\n", chunk_size) + self.assert_event_tags(parser, [ +- ('end', '{namespace}element'), +- ('end', '{namespace}empty-element'), ++ ('end', 'element'), ++ ('end', 'empty-element'), + ]) +- self._feed(parser, "\n") +- self.assert_event_tags(parser, [('end', '{namespace}root')]) ++ self._feed(parser, "\n", chunk_size) ++ self.assert_event_tags(parser, [('end', 'root')]) + self.assertIsNone(parser.close()) + ++ @fails_with_expat ++ def test_simple_xml_chunk_1(self): ++ self.test_simple_xml(chunk_size=1) ++ ++ @fails_with_expat ++ 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_ns_events(self): + parser = ET.XMLPullParser(events=('start-ns', 'end-ns')) + self._feed(parser, "\n") diff --git a/python3.spec b/python3.spec index 6da98d2..b9cb5f5 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.9.9 -Release: 28 +Release: 29 License: Python-2.0 %global branchversion 3.9 @@ -109,6 +109,9 @@ Patch6015: backport-CVE-2007-4559.patch Patch6016: backport-CVE-2023-40217.patch Patch6017: backport-3.9-gh-104049-do-not-expose-on-disk-location-from-Si.patch Patch6018: backport-3.9-gh-99889-Fix-directory-traversal-security-flaw-i.patch +Patch6019: backport-3.9-gh-114572-Fix-locking-in-cert_store_stats-and-ge.patch +Patch6020: backport-fix_xml_tree_assert_error.patch +Patch6021: update-openssl-version-for-test-case.patch Patch9000: add-the-sm3-method-for-obtaining-the-salt-value.patch Patch9001: python3-Add-sw64-architecture.patch @@ -216,6 +219,9 @@ rm -r Modules/expat %patch6016 -p1 %patch6017 -p1 %patch6018 -p1 +%patch6019 -p1 +%patch6020 -p1 +%patch6021 -p1 %patch9000 -p1 %patch9001 -p1 @@ -843,6 +849,15 @@ export BEP_GTDLIST="$BEP_GTDLIST_TMP" %{_mandir}/*/* %changelog +* Web Jul 10 2024 xinsheng - 3.9.9-29 +- Type:bugfix +- CVE:NA +- SUG:NA +- DESC:backport upstream patches + - Fix locking in cert_store_stats and get_ca_certs + - Fix xml tree assert error + - Update openssl version for test case + * Wed Oct 25 zhuofeng - 3.9.9-28 - Type:bugfix - CVE:NA diff --git a/update-openssl-version-for-test-case.patch b/update-openssl-version-for-test-case.patch new file mode 100644 index 0000000..0cc9781 --- /dev/null +++ b/update-openssl-version-for-test-case.patch @@ -0,0 +1,25 @@ +From d7a637e43086c51d0e2b4cd2f9324f1c60eced50 Mon Sep 17 00:00:00 2001 +From: xinsheng3 +Date: Thu, 20 Jun 2024 15:29:05 +0800 +Subject: [PATCH] update openssl version for test case.patch + +--- + Lib/test/test_ssl.py | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/Lib/test/test_ssl.py b/Lib/test/test_ssl.py +index 2c71c27..d95f0ef 100644 +--- a/Lib/test/test_ssl.py ++++ b/Lib/test/test_ssl.py +@@ -589,7 +589,7 @@ class BasicSocketTests(unittest.TestCase): + self.assertGreaterEqual(fix, 0) + self.assertLess(fix, 256) + self.assertGreaterEqual(patch, 0) +- self.assertLessEqual(patch, 63) ++ self.assertLessEqual(patch, 128) + self.assertGreaterEqual(status, 0) + self.assertLessEqual(status, 15) + # Version string as returned by {Open,Libre}SSL, the format might change +-- +2.33.0 + -- Gitee