Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix crash on config reload with BoringSSL #9840

Merged
merged 1 commit into from
Jun 16, 2023

Conversation

maskit
Copy link
Member

@maskit maskit commented Jun 14, 2023

ATS crashed due to double free if it reloads a cert file that contains chained certs.

According to BoringSSL documentation,

SSL_CTX_add_extra_chain_cert calls SSL_CTX_add0_chain_cert.

and

SSL_CTX_add0_chain_cert appends x509 to ctx's certificate chain. On success, it returns one and takes ownership of x509. Otherwise, it returns zero.
OPENSSL_EXPORT int SSL_CTX_add0_chain_cert(SSL_CTX *ctx, X509 *x509);

So we cannot free cert here.

It kinda made sense before #9177 because we used to call SSL_CTX_use_certificate here instead (which is incorrect as the PR explains) and SSL_CTX_use_certificate does not seem like to take ownership according to BoringSSL documentation.

SSL_CTX_use_certificate sets ctx's leaf certificate to x509. It returns one on success and zero on failure.

I checked OpenSSL's implementation and it looks like OpenSSL takes ownership too. The behavior is the same, but BoringSSL aborts during the second free because of internal sanity check. I don't think we need ifdef for BoringSSL.

@maskit maskit added this to the 10.0.0 milestone Jun 14, 2023
@maskit maskit self-assigned this Jun 14, 2023
@@ -952,7 +952,8 @@ SSLConfigParams::getCTX(const std::string &client_cert, const std::string &key_f
SSLError("failed to attach client chain certificate from %s", client_cert.c_str());
goto fail;
}
X509_free(cert);
// Do not free cert becasue SSL_CTX_add_extra_chain_cert takes ownership of cert if it succeeds, unlike
// SSL_CTX_use_certificate.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If SSL_CTX_add_extra_chain_cert, but a subsequent operation fails, we would free the certificate at the failed label. Wouldn't that also be a double free when the SSL_CTX is freed?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure if I understand your comment correctly.

If SSL_CTX_add_extra_chain_cert succeeds, PEM_read_bio_X509 will be called. And if that fails, cert is nullptr and we leave this while loop. Since cert is nullptr, it won't be freed even if we go to fail label later.

If SSL_CTX_add_extra_chain_cert fails, SSL_CTX doesn't have ownership, so the cert has to be freed. We jump to fail label, and the cert will be freed.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, I missed the extra read at the end of the loop. IMHO, writing it like this would be a lot clearer:

      // Continue to fetch certs to associate intermediate certificates.
      while ((cert = PEM_read_bio_X509(biop, nullptr, nullptr, nullptr)) {
          if (!SSL_CTX_add_extra_chain_cert(client_ctx.get(), cert)) {
            SSLError("failed to attach client chain certificate from %s", client_cert.c_str());
            goto fail;
          }
      }

@jpeach
Copy link
Contributor

jpeach commented Jun 15, 2023

While I'm looking at this code, it seems a bit fragile that cleanup_bio is non-static and is the one to set BIO_NOCLOSE, rather than setting it at BIO_new_mem_buf create time (since cleanup_bio should easily be applied to a BIO that does actually own its memory).

@maskit maskit merged commit b0f4a04 into apache:master Jun 16, 2023
zwoop pushed a commit that referenced this pull request Jul 3, 2023
@zwoop
Copy link
Contributor

zwoop commented Jul 3, 2023

Cherry-picked to v9.2.x

@zwoop zwoop modified the milestones: 10.0.0, 9.2.2 Jul 3, 2023
cmcfarlen pushed a commit to cmcfarlen/trafficserver that referenced this pull request Jun 3, 2024
* asf/master: (90 commits)
  doc: fix the internal libraries section formatting (apache#9879)
  Add max thread count options to CMake build (apache#9883)
  Add yaml libs reference to HTTP proxy test suite. Closes apache#9882 (apache#9885)
  Add transparent proxy support to CMake build (apache#9884)
  Check for symbol IP_TOS in CMake build (apache#9870)
  RAT license fix: renamed_records.out -> .gold (apache#9876)
  Add traffic_wccp to CMake build (apache#9867)
  cleanup cast warning with reinterpret_cast (apache#9866)
  Fixes Coverity 1513058, introduced with apache#9643 (apache#9860)
  add some missing libs for clang (apache#9865)
  Add support for libunwind in CMake build (apache#9862)
  Add option to build regression tests (apache#9863)
  Fix crash on config reload with BoringSSL (apache#9840)
  Check for SO_PEERCRED in CMake build (apache#9855)
  Check for SO_MARK in CMake build (apache#9854)
  Clean up UnixNetProcessor entanglements. (apache#9825)
  Remove unneeded DEBUG conditionals. (apache#9849)
  Add option to enable fast SDK in CMake build (apache#9853)
  Add support for POSIX Cap in CMake build (apache#9852)
  WCCP: remove ts::Buffer (apache#9824)
  ...
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants