[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#943846: buster-pu: package python-cryptography/2.6.1-3+deb10u2



Package: release.debian.org
Severity: normal
Tags: buster
User: release.debian.org@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 <jmm@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.kehrer@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.kehrer@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

Reply to: