Package: release.debian.org Severity: normal Tags: buster User: release.debian....@packages.debian.org Usertags: pu
(This is a followup update on top of the +deb10u1 already in s-p-u, I've reached out to Tristan beforehand) Attached debdiff fixes a memory leak in python-cryptography, which was noticed in an ACME-related service (https://wikitech.wikimedia.org/wiki/Acme-chief) running on Buster. It has been verified that the updated packages fix the memory leak (and are otherwise working fine as well). Debdiff below. Cheers, Moritz diff -Nru python-cryptography-2.6.1/debian/changelog python-cryptography-2.6.1/debian/changelog --- python-cryptography-2.6.1/debian/changelog 2019-09-30 20:55:00.000000000 +0200 +++ python-cryptography-2.6.1/debian/changelog 2019-10-18 16:08:59.000000000 +0200 @@ -1,3 +1,13 @@ +python-cryptography (2.6.1-3+deb10u2) buster; urgency=medium + + * Cherrypick 92241410b5b0591d849443b3023992334a4be0a2 and + 9a22851fab924fd58482fdad3f8dd23dc3987f91 from upstream which + addresses a memory leak triggerable when parsing x509 + certificate extensions like AIA, thanks to Valentin + Gutierrez for the report (Closes: #941413) + + -- Moritz Mühlenhoff <j...@debian.org> Fri, 18 Oct 2019 16:08:59 +0200 + python-cryptography (2.6.1-3+deb10u1) buster; urgency=medium * Non-maintainer upload. diff -Nru python-cryptography-2.6.1/debian/patches/aia-memleak-1.patch python-cryptography-2.6.1/debian/patches/aia-memleak-1.patch --- python-cryptography-2.6.1/debian/patches/aia-memleak-1.patch 1970-01-01 01:00:00.000000000 +0100 +++ python-cryptography-2.6.1/debian/patches/aia-memleak-1.patch 2019-10-18 16:08:35.000000000 +0200 @@ -0,0 +1,94 @@ +From 92241410b5b0591d849443b3023992334a4be0a2 Mon Sep 17 00:00:00 2001 +From: Paul Kehrer <paul.l.keh...@gmail.com> +Date: Thu, 11 Apr 2019 20:57:13 +0800 +Subject: [PATCH] fix a memory leak in AIA parsing (#4836) + +* fix a memory leak in AIA parsing + +* oops can't remove that +--- + src/_cffi_src/openssl/x509v3.py | 3 +++ + .../hazmat/backends/openssl/decode_asn1.py | 9 +++++++- + tests/hazmat/backends/test_openssl_memleak.py | 21 ++++++++++++++++++- + 3 files changed, 31 insertions(+), 2 deletions(-) + +diff --git a/src/_cffi_src/openssl/x509v3.py b/src/_cffi_src/openssl/x509v3.py +index 193d2e233b..5968120652 100644 +--- a/src/_cffi_src/openssl/x509v3.py ++++ b/src/_cffi_src/openssl/x509v3.py +@@ -177,6 +177,7 @@ + typedef void (*sk_GENERAL_NAME_freefunc)(GENERAL_NAME *); + typedef void (*sk_DIST_POINT_freefunc)(DIST_POINT *); + typedef void (*sk_POLICYINFO_freefunc)(POLICYINFO *); ++typedef void (*sk_ACCESS_DESCRIPTION_freefunc)(ACCESS_DESCRIPTION *); + """ + + +@@ -228,6 +229,8 @@ + Cryptography_STACK_OF_ACCESS_DESCRIPTION *, int + ); + void sk_ACCESS_DESCRIPTION_free(Cryptography_STACK_OF_ACCESS_DESCRIPTION *); ++void sk_ACCESS_DESCRIPTION_pop_free(Cryptography_STACK_OF_ACCESS_DESCRIPTION *, ++ sk_ACCESS_DESCRIPTION_freefunc); + int sk_ACCESS_DESCRIPTION_push(Cryptography_STACK_OF_ACCESS_DESCRIPTION *, + ACCESS_DESCRIPTION *); + +diff --git a/src/cryptography/hazmat/backends/openssl/decode_asn1.py b/src/cryptography/hazmat/backends/openssl/decode_asn1.py +index 773189d4f8..75d5844bc1 100644 +--- a/src/cryptography/hazmat/backends/openssl/decode_asn1.py ++++ b/src/cryptography/hazmat/backends/openssl/decode_asn1.py +@@ -379,7 +379,14 @@ def _decode_authority_key_identifier(backend, akid): + + def _decode_authority_information_access(backend, aia): + aia = backend._ffi.cast("Cryptography_STACK_OF_ACCESS_DESCRIPTION *", aia) +- aia = backend._ffi.gc(aia, backend._lib.sk_ACCESS_DESCRIPTION_free) ++ aia = backend._ffi.gc( ++ aia, ++ lambda x: backend._lib.sk_ACCESS_DESCRIPTION_pop_free( ++ x, backend._ffi.addressof( ++ backend._lib._original_lib, "ACCESS_DESCRIPTION_free" ++ ) ++ ) ++ ) + num = backend._lib.sk_ACCESS_DESCRIPTION_num(aia) + access_descriptions = [] + for i in range(num): +diff --git a/tests/hazmat/backends/test_openssl_memleak.py b/tests/hazmat/backends/test_openssl_memleak.py +index ed22b5db9e..f9ae1c46b9 100644 +--- a/tests/hazmat/backends/test_openssl_memleak.py ++++ b/tests/hazmat/backends/test_openssl_memleak.py +@@ -210,7 +210,7 @@ class TestOpenSSLMemoryLeaks(object): + @pytest.mark.parametrize("path", [ + "x509/PKITS_data/certs/ValidcRLIssuerTest28EE.crt", + ]) +- def test_x509_certificate_extensions(self, path): ++ def test_der_x509_certificate_extensions(self, path): + assert_no_memory_leaks(textwrap.dedent(""" + def func(path): + from cryptography import x509 +@@ -226,6 +226,25 @@ def func(path): + cert.extensions + """), [path]) + ++ @pytest.mark.parametrize("path", [ ++ "x509/cryptography.io.pem", ++ ]) ++ def test_pem_x509_certificate_extensions(self, path): ++ assert_no_memory_leaks(textwrap.dedent(""" ++ def func(path): ++ from cryptography import x509 ++ from cryptography.hazmat.backends.openssl import backend ++ ++ import cryptography_vectors ++ ++ with cryptography_vectors.open_vector_file(path, "rb") as f: ++ cert = x509.load_pem_x509_certificate( ++ f.read(), backend ++ ) ++ ++ cert.extensions ++ """), [path]) ++ + def test_x509_csr_extensions(self): + assert_no_memory_leaks(textwrap.dedent(""" + def func(): diff -Nru python-cryptography-2.6.1/debian/patches/aia-memleak-2.patch python-cryptography-2.6.1/debian/patches/aia-memleak-2.patch --- python-cryptography-2.6.1/debian/patches/aia-memleak-2.patch 1970-01-01 01:00:00.000000000 +0100 +++ python-cryptography-2.6.1/debian/patches/aia-memleak-2.patch 2019-10-18 16:08:35.000000000 +0200 @@ -0,0 +1,181 @@ +From 9a22851fab924fd58482fdad3f8dd23dc3987f91 Mon Sep 17 00:00:00 2001 +From: Paul Kehrer <paul.l.keh...@gmail.com> +Date: Sat, 18 May 2019 16:37:54 -0400 +Subject: [PATCH] fix aia encoding memory leak (#4889) + +* fix aia encoding memory leak + +* don't return anything from the prealloc func +--- + .../hazmat/backends/openssl/encode_asn1.py | 27 +++++---- + tests/hazmat/backends/test_openssl_memleak.py | 60 +++++++++++++++++++ + 2 files changed, 75 insertions(+), 12 deletions(-) + +diff --git a/src/cryptography/hazmat/backends/openssl/encode_asn1.py b/src/cryptography/hazmat/backends/openssl/encode_asn1.py +index 61cfd14de0..a774daa788 100644 +--- a/src/cryptography/hazmat/backends/openssl/encode_asn1.py ++++ b/src/cryptography/hazmat/backends/openssl/encode_asn1.py +@@ -345,16 +345,22 @@ def _encode_authority_information_access(backend, authority_info_access): + aia = backend._lib.sk_ACCESS_DESCRIPTION_new_null() + backend.openssl_assert(aia != backend._ffi.NULL) + aia = backend._ffi.gc( +- aia, backend._lib.sk_ACCESS_DESCRIPTION_free ++ aia, ++ lambda x: backend._lib.sk_ACCESS_DESCRIPTION_pop_free( ++ x, backend._ffi.addressof( ++ backend._lib._original_lib, "ACCESS_DESCRIPTION_free" ++ ) ++ ) + ) + for access_description in authority_info_access: + ad = backend._lib.ACCESS_DESCRIPTION_new() + method = _txt2obj( + backend, access_description.access_method.dotted_string + ) +- gn = _encode_general_name(backend, access_description.access_location) ++ _encode_general_name_preallocated( ++ backend, access_description.access_location, ad.location ++ ) + ad.method = method +- ad.location = gn + res = backend._lib.sk_ACCESS_DESCRIPTION_push(aia, ad) + backend.openssl_assert(res >= 1) + +@@ -385,8 +391,13 @@ def _encode_subject_key_identifier(backend, ski): + + + def _encode_general_name(backend, name): ++ gn = backend._lib.GENERAL_NAME_new() ++ _encode_general_name_preallocated(backend, name, gn) ++ return gn ++ ++ ++def _encode_general_name_preallocated(backend, name, gn): + if isinstance(name, x509.DNSName): +- gn = backend._lib.GENERAL_NAME_new() + backend.openssl_assert(gn != backend._ffi.NULL) + gn.type = backend._lib.GEN_DNS + +@@ -400,7 +411,6 @@ def _encode_general_name(backend, name): + backend.openssl_assert(res == 1) + gn.d.dNSName = ia5 + elif isinstance(name, x509.RegisteredID): +- gn = backend._lib.GENERAL_NAME_new() + backend.openssl_assert(gn != backend._ffi.NULL) + gn.type = backend._lib.GEN_RID + obj = backend._lib.OBJ_txt2obj( +@@ -409,13 +419,11 @@ def _encode_general_name(backend, name): + backend.openssl_assert(obj != backend._ffi.NULL) + gn.d.registeredID = obj + elif isinstance(name, x509.DirectoryName): +- gn = backend._lib.GENERAL_NAME_new() + backend.openssl_assert(gn != backend._ffi.NULL) + dir_name = _encode_name(backend, name.value) + gn.type = backend._lib.GEN_DIRNAME + gn.d.directoryName = dir_name + elif isinstance(name, x509.IPAddress): +- gn = backend._lib.GENERAL_NAME_new() + backend.openssl_assert(gn != backend._ffi.NULL) + if isinstance(name.value, ipaddress.IPv4Network): + packed = ( +@@ -433,7 +441,6 @@ def _encode_general_name(backend, name): + gn.type = backend._lib.GEN_IPADD + gn.d.iPAddress = ipaddr + elif isinstance(name, x509.OtherName): +- gn = backend._lib.GENERAL_NAME_new() + backend.openssl_assert(gn != backend._ffi.NULL) + other_name = backend._lib.OTHERNAME_new() + backend.openssl_assert(other_name != backend._ffi.NULL) +@@ -456,7 +463,6 @@ def _encode_general_name(backend, name): + gn.type = backend._lib.GEN_OTHERNAME + gn.d.otherName = other_name + elif isinstance(name, x509.RFC822Name): +- gn = backend._lib.GENERAL_NAME_new() + backend.openssl_assert(gn != backend._ffi.NULL) + # ia5strings are supposed to be ITU T.50 but to allow round-tripping + # of broken certs that encode utf8 we'll encode utf8 here too. +@@ -465,7 +471,6 @@ def _encode_general_name(backend, name): + gn.type = backend._lib.GEN_EMAIL + gn.d.rfc822Name = asn1_str + elif isinstance(name, x509.UniformResourceIdentifier): +- gn = backend._lib.GENERAL_NAME_new() + backend.openssl_assert(gn != backend._ffi.NULL) + # ia5strings are supposed to be ITU T.50 but to allow round-tripping + # of broken certs that encode utf8 we'll encode utf8 here too. +@@ -478,8 +483,6 @@ def _encode_general_name(backend, name): + "{} is an unknown GeneralName type".format(name) + ) + +- return gn +- + + def _encode_extended_key_usage(backend, extended_key_usage): + eku = backend._lib.sk_ASN1_OBJECT_new_null() +diff --git a/tests/hazmat/backends/test_openssl_memleak.py b/tests/hazmat/backends/test_openssl_memleak.py +index f9ae1c46b9..935ea3dfe3 100644 +--- a/tests/hazmat/backends/test_openssl_memleak.py ++++ b/tests/hazmat/backends/test_openssl_memleak.py +@@ -389,3 +389,63 @@ def func(): + x509.IssuingDistributionPoint + ) + """)) ++ ++ def test_create_certificate_with_extensions(self): ++ assert_no_memory_leaks(textwrap.dedent(""" ++ def func(): ++ import datetime ++ ++ from cryptography import x509 ++ from cryptography.hazmat.backends.openssl import backend ++ from cryptography.hazmat.primitives import hashes ++ from cryptography.hazmat.primitives.asymmetric import ec ++ from cryptography.x509.oid import ( ++ AuthorityInformationAccessOID, ExtendedKeyUsageOID, NameOID ++ ) ++ ++ private_key = ec.generate_private_key(ec.SECP256R1(), backend) ++ ++ not_valid_before = datetime.datetime.now() ++ not_valid_after = not_valid_before + datetime.timedelta(days=365) ++ ++ aia = x509.AuthorityInformationAccess([ ++ x509.AccessDescription( ++ AuthorityInformationAccessOID.OCSP, ++ x509.UniformResourceIdentifier(u"http://ocsp.domain.com") ++ ), ++ x509.AccessDescription( ++ AuthorityInformationAccessOID.CA_ISSUERS, ++ x509.UniformResourceIdentifier(u"http://domain.com/ca.crt") ++ ) ++ ]) ++ sans = [u'*.example.org', u'foobar.example.net'] ++ san = x509.SubjectAlternativeName(list(map(x509.DNSName, sans))) ++ ++ ski = x509.SubjectKeyIdentifier.from_public_key( ++ private_key.public_key() ++ ) ++ eku = x509.ExtendedKeyUsage([ ++ ExtendedKeyUsageOID.CLIENT_AUTH, ++ ExtendedKeyUsageOID.SERVER_AUTH, ++ ExtendedKeyUsageOID.CODE_SIGNING, ++ ]) ++ ++ builder = x509.CertificateBuilder().serial_number( ++ 777 ++ ).issuer_name(x509.Name([ ++ x509.NameAttribute(NameOID.COUNTRY_NAME, u'US'), ++ ])).subject_name(x509.Name([ ++ x509.NameAttribute(NameOID.COUNTRY_NAME, u'US'), ++ ])).public_key( ++ private_key.public_key() ++ ).add_extension( ++ aia, critical=False ++ ).not_valid_before( ++ not_valid_before ++ ).not_valid_after( ++ not_valid_after ++ ) ++ ++ cert = builder.sign(private_key, hashes.SHA256(), backend) ++ cert.extensions ++ """)) diff -Nru python-cryptography-2.6.1/debian/patches/series python-cryptography-2.6.1/debian/patches/series --- python-cryptography-2.6.1/debian/patches/series 2019-09-24 20:38:45.000000000 +0200 +++ python-cryptography-2.6.1/debian/patches/series 2019-10-18 16:08:51.000000000 +0200 @@ -1,3 +1,5 @@ update-our-test-to-be-more-robust-wrt-some-changes-f.patch use-a-random-key-for-these-tests-4887.patch tests-Skip-test_load_ecdsa_no_named_curve.patch +aia-memleak-1.patch +aia-memleak-2.patch