Uploaded image for project: 'Qt'
  1. Qt
  2. QTBUG-66937

Memory Leaks in macOS's SSL implementation: SecTrustSettingsCopyCertificates and ensureInitialized

    XMLWordPrintable

Details

    • Bug
    • Resolution: Done
    • P2: Important
    • 5.11.0
    • 5.10.1, 5.11.0 Beta 1
    • Network: SSL
    • None
    • macOS 10.13.3
    • macOS
    • c2373fce3c112a0e497ab1de5dfe670ad8aa59c5

    Description

      Using ASAN with clang5 I found the following potential leaks:

      Direct leak of 44 byte(s) in 1 object(s) allocated from:
      #0 0x103707ac3 in wrap_malloc (libclang_rt.asan_osx_dynamic.dylib:x86_64h+0x57ac3)
      #1 0x7fff60a818b2 in _Block_copy (libsystem_blocks.dylib:x86_64+0x8b2)
      #2 0x7fff609f9fd3 in _dispatch_Block_copy (libdispatch.dylib:x86_64+0x1fd3)
      #3 0x7fff609fb070 in dispatch_source_set_event_handler (libdispatch.dylib:x86_64+0x3070)
      #4 0x103707049 in wrap_dispatch_source_set_event_handler (libclang_rt.asan_osx_dynamic.dylib:x86_64h+0x57049)
      #5 0x7fff60949193 in ccrng_cryptographic_init_once (libcorecrypto.dylib:x86_64+0x5e193)
      #6 0x7fff609f9d4f in _dispatch_client_callout (libdispatch.dylib:x86_64+0x1d4f)
      #7 0x7fff609f9d02 in dispatch_once_f (libdispatch.dylib:x86_64+0x1d02)
      #8 0x7fff609495b5 in ccrng (libcorecrypto.dylib:x86_64+0x5e5b5)
      #9 0x7fff608d562b in ccDRBGGetRngState (libcommonCrypto.dylib:x86_64+0x662b)
      #10 0x7fff44ee3e83 in SSLCreateInternalRecordLayer (Security:x86_64+0x229e83)
      #11 0x7fff44ee1bea in SSLCreateContext (Security:x86_64+0x227bea)
      #12 0x103632eae in qt_createSecureTransportContext(QSslSocket::SslMode) (QtNetwork:x86_64+0xe1eae)
      #13 0x103632a14 in QSslSocketPrivate::ensureInitialized() (QtNetwork:x86_64+0xe1a14)
      #14 0x103627ece in QSslConfigurationPrivate::defaultConfiguration() (QtNetwork:x86_64+0xd6ece)
      #15 0x10361f7dd in QSslConfiguration::defaultConfiguration() (QtNetwork:x86_64+0xce7dd)
      #16 0x103584e60 in QNetworkRequest::sslConfiguration() const (QtNetwork:x86_64+0x33e60)
      #17 0x10358d732 in QNetworkReplyHttpImpl::QNetworkReplyHttpImpl(QNetworkAccessManager*, QNetworkRequest const&, QNetworkAccessManager::Operation&, QIODevice*) (QtNetwork:x86_64+0x3c732)
      #18 0x103573e69 in QNetworkAccessManager::createRequest(QNetworkAccessManager::Operation, QNetworkRequest const&, QIODevice*) (QtNetwork:x86_64+0x22e69)
      #19 0x10357231d in QNetworkAccessManager::post(QNetworkRequest const&, QByteArray const&) (QtNetwork:x86_64+0x2131d)
      

      And more importantly

      Indirect leak of 198116 byte(s) in 175 object(s) allocated from:
          #0 0x103707ac3 in wrap_malloc (libclang_rt.asan_osx_dynamic.dylib:x86_64h+0x57ac3)
          #1 0x7fff44cbc083 in DefaultAllocator::malloc(unsigned long) (Security:x86_64+0x2083)
          #2 0x7fff44e531f8 in Security::KeychainCore::ItemImpl::ItemImpl(SecItemClass, SecKeychainAttributeList*, unsigned int, void const*) (Security:x86_64+0x1991f8)
          #3 0x7fff44cbbe03 in Security::KeychainCore::Certificate::Certificate(cssm_data const&, unsigned int, unsigned int) (Security:x86_64+0x1e03)
          #4 0x7fff44e6e010 in SecCertificateCreateItemImplInstance (Security:x86_64+0x1b4010)
          #5 0x7fff44cca0db in SecCertificateGetData (Security:x86_64+0x100db)
          #6 0x7fff44e9e848 in SecTrustSettingsCertHashStrFromCert (Security:x86_64+0x1e4848)
          #7 0x7fff44eb44e4 in Security::KeychainCore::TrustSettings::findDictionaryForCert(OpaqueSecCertificateRef*) (Security:x86_64+0x1fa4e4)
          #8 0x7fff44eb41f4 in Security::KeychainCore::TrustSettings::findQualifiedCerts(std::__1::vector<Security::KeychainCore::Keychain, std::__1::allocator<Security::KeychainCore::Keychain> >&, bool, bool, cssm_data const*, char const*, unsigned int, __CFArray*) (Security:x86_64+0x1fa1f4)
          #9 0x7fff44eb40da in Security::KeychainCore::TrustSettings::findCerts(std::__1::vector<Security::KeychainCore::Keychain, std::__1::allocator<Security::KeychainCore::Keychain> >&, __CFArray*) (Security:x86_64+0x1fa0da)
          #10 0x7fff44e9f132 in SecTrustSettingsCopyCertificates (Security:x86_64+0x1e5132)
          #11 0x10363255b in QSslSocketPrivate::systemCaCertificates() (QtNetwork:x86_64+0xe155b)
          #12 0x103632c39 in QSslSocketPrivate::ensureInitialized() (QtNetwork:x86_64+0xe1c39)
          #13 0x103627ece in QSslConfigurationPrivate::defaultConfiguration() (QtNetwork:x86_64+0xd6ece)
          #14 0x10361f7dd in QSslConfiguration::defaultConfiguration() (QtNetwork:x86_64+0xce7dd)
          #15 0x103584e60 in QNetworkRequest::sslConfiguration() const (QtNetwork:x86_64+0x33e60)
          #16 0x10358d732 in QNetworkReplyHttpImpl::QNetworkReplyHttpImpl(QNetworkAccessManager*, QNetworkRequest const&, QNetworkAccessManager::Operation&, QIODevice*) (QtNetwork:x86_64+0x3c732)
          #17 0x103573e69 in QNetworkAccessManager::createRequest(QNetworkAccessManager::Operation, QNetworkRequest const&, QIODevice*) (QtNetwork:x86_64+0x22e69)
          #18 0x10357231d in QNetworkAccessManager::post(QNetworkRequest const&, QByteArray const&) (QtNetwork:x86_64+0x2131d)
      

      qsslsocket_mac.cpp and qsslsocket_mac_shared.cpp are responsible for this, respectively.
      I quickly analyzed it and I have found a quick fix for a small leak in qsslsocket_mac_shared.cpp:

      @@ -128,10 +128,10 @@ QList<QSslCertificate> QSslSocketPrivate::systemCaCertificates()
      QList<QSslCertificate> systemCerts;
      // SecTrustSettingsCopyCertificates is not defined on iOS.
      #ifdef Q_OS_OSX
      - QCFType<CFArrayRef> cfCerts;
      // iterate through all enum members, order:
      // kSecTrustSettingsDomainUser, kSecTrustSettingsDomainAdmin, kSecTrustSettingsDomainSystem
      for (int dom = kSecTrustSettingsDomainUser; dom <= int(kSecTrustSettingsDomainSystem); dom++) {
      + QCFType<CFArrayRef> cfCerts;
      OSStatus status = SecTrustSettingsCopyCertificates(SecTrustSettingsDomain(dom), &cfCerts);
      if (status == noErr) {
      const CFIndex size = CFArrayGetCount(cfCerts);
      

      However, there are still lots of data leaked. So, it seems that even after my proposed change of moving QCFType, I still see leaks from SecTrustSettingsCopyCertificates that I assume are internal and there's nothing we can do.

      Please find attached a simple example which uses ASAN to detect the leak. In macOS you'll need a newer clang than the one provided by Apple. I installed clang5 with brew.

      I have also attached 2 screenshots of Instruments showing how it does consider that a leak. I'm not sure we can really do something about it if it's just Apple's code, though.

       

      Attachments

        For Gerrit Dashboard: QTBUG-66937
        # Subject Branch Project Status CR V

        Activity

          People

            tpochep Timur Pocheptsov
            pamarcos Pablo Marcos Oltra
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved:

              Gerrit Reviews

                There are no open Gerrit changes