From ed9e4d252512f42a5f6843f835ead80b0eb0a987 Mon Sep 17 00:00:00 2001 From: Spencer Jackson Date: Wed, 8 Jan 2020 16:20:47 +0000 Subject: SERVER-38945: Cache OpenSSL error states to elide error clearing (cherry picked from commit 0842ea78e70147501c92f188706b0c161b3ac76e) --- .../asio/include/asio/ssl/detail/engine.hpp | 2 + .../asio/include/asio/ssl/detail/impl/engine.ipp | 27 ++++++++-- ...5-Cache-OpenSSL-error-states-to-elide-err.patch | 62 ++++++++++++++++++++++ ...3-Disable-SSL_MODE_RELEASE_BUFFERS-in-ASI.patch | 34 ++++++++++++ 4 files changed, 120 insertions(+), 5 deletions(-) create mode 100644 src/third_party/asio-master/patches/0003-SERVER-38945-Cache-OpenSSL-error-states-to-elide-err.patch create mode 100644 src/third_party/asio-master/patches/0004-SERVER-40393-Disable-SSL_MODE_RELEASE_BUFFERS-in-ASI.patch diff --git a/src/third_party/asio-master/asio/include/asio/ssl/detail/engine.hpp b/src/third_party/asio-master/asio/include/asio/ssl/detail/engine.hpp index 061a50dd2ac..b256b063baf 100644 --- a/src/third_party/asio-master/asio/include/asio/ssl/detail/engine.hpp +++ b/src/third_party/asio-master/asio/include/asio/ssl/detail/engine.hpp @@ -121,6 +121,8 @@ private: ASIO_DECL static asio::detail::static_mutex& accept_mutex(); #endif // (OPENSSL_VERSION_NUMBER < 0x10000000L) + ASIO_DECL void purge_error_state(); + // Perform one operation. Returns >= 0 on success or error, want_read if the // operation needs more input, or want_write if it needs to write some output // before the operation can complete. diff --git a/src/third_party/asio-master/asio/include/asio/ssl/detail/impl/engine.ipp b/src/third_party/asio-master/asio/include/asio/ssl/detail/impl/engine.ipp index d55bc87f59d..077a1a1948c 100644 --- a/src/third_party/asio-master/asio/include/asio/ssl/detail/impl/engine.ipp +++ b/src/third_party/asio-master/asio/include/asio/ssl/detail/impl/engine.ipp @@ -46,10 +46,10 @@ engine::engine(SSL_CTX* context) ::SSL_set_mode(ssl_, SSL_MODE_ENABLE_PARTIAL_WRITE); ::SSL_set_mode(ssl_, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER); -// SERVER-40393 - Disable SSL_MODE_RELEASE_BUFFERS in ASIO -//#if defined(SSL_MODE_RELEASE_BUFFERS) - //::SSL_set_mode(ssl_, SSL_MODE_RELEASE_BUFFERS); -//#endif // defined(SSL_MODE_RELEASE_BUFFERS) + // SERVER-40393 - Disable SSL_MODE_RELEASE_BUFFERS in ASIO + //#if defined(SSL_MODE_RELEASE_BUFFERS) + //::SSL_set_mode(ssl_, SSL_MODE_RELEASE_BUFFERS); + //#endif // defined(SSL_MODE_RELEASE_BUFFERS) ::BIO* int_bio = 0; ::BIO_new_bio_pair(&int_bio, 0, &ext_bio_, 0); @@ -226,12 +226,29 @@ asio::detail::static_mutex& engine::accept_mutex() } #endif // (OPENSSL_VERSION_NUMBER < 0x10000000L) +void engine::purge_error_state() { +#if (OPENSSL_VERSION_NUMBER < 0x1010000fL && !defined(__APPLE__)) + // OpenSSL 1.1.0 introduced a thread local state storage mechanism. + // Versions prior sometimes had contention issues on global mutexes + // which protected thread local state. + // If we are compiled against a version without native thread local + // support, cache a pointer to this thread's error state, which we can + // access without contention. If that state requires no cleanup, + // we can avoid invoking OpenSSL's more expensive machinery. + const static thread_local ERR_STATE* es = ERR_get_state(); + if (es->bottom == es->top) { + return; + } +#endif // (OPENSSL_VERSION_NUMBER < 0x1010000fL && !defined(__APPLE__)) + ::ERR_clear_error(); +} + engine::want engine::perform(int (engine::* op)(void*, std::size_t), void* data, std::size_t length, asio::error_code& ec, std::size_t* bytes_transferred) { std::size_t pending_output_before = ::BIO_ctrl_pending(ext_bio_); - ::ERR_clear_error(); + purge_error_state(); int result = (this->*op)(data, length); int ssl_error = ::SSL_get_error(ssl_, result); int sys_error = static_cast(::ERR_get_error()); diff --git a/src/third_party/asio-master/patches/0003-SERVER-38945-Cache-OpenSSL-error-states-to-elide-err.patch b/src/third_party/asio-master/patches/0003-SERVER-38945-Cache-OpenSSL-error-states-to-elide-err.patch new file mode 100644 index 00000000000..1a1939acf47 --- /dev/null +++ b/src/third_party/asio-master/patches/0003-SERVER-38945-Cache-OpenSSL-error-states-to-elide-err.patch @@ -0,0 +1,62 @@ +From 5f1ffc409805a3279b09e2d2a005f3f744895348 Mon Sep 17 00:00:00 2001 +From: Spencer Jackson +Date: Fri, 17 May 2019 12:58:57 -0400 +Subject: [PATCH 3/4] SERVER-38945: Cache OpenSSL error states to elide error + clearing + +--- + asio/include/asio/ssl/detail/engine.hpp | 2 ++ + asio/include/asio/ssl/detail/impl/engine.ipp | 19 ++++++++++++++++++- + 2 files changed, 20 insertions(+), 1 deletion(-) + +diff --git a/asio/include/asio/ssl/detail/engine.hpp b/asio/include/asio/ssl/detail/engine.hpp +index 061a50dd..b256b063 100644 +--- a/asio/include/asio/ssl/detail/engine.hpp ++++ b/asio/include/asio/ssl/detail/engine.hpp +@@ -121,6 +121,8 @@ private: + ASIO_DECL static asio::detail::static_mutex& accept_mutex(); + #endif // (OPENSSL_VERSION_NUMBER < 0x10000000L) + ++ ASIO_DECL void purge_error_state(); ++ + // Perform one operation. Returns >= 0 on success or error, want_read if the + // operation needs more input, or want_write if it needs to write some output + // before the operation can complete. +diff --git a/asio/include/asio/ssl/detail/impl/engine.ipp b/asio/include/asio/ssl/detail/impl/engine.ipp +index 345461b1..310c838d 100644 +--- a/asio/include/asio/ssl/detail/impl/engine.ipp ++++ b/asio/include/asio/ssl/detail/impl/engine.ipp +@@ -225,12 +225,29 @@ asio::detail::static_mutex& engine::accept_mutex() + } + #endif // (OPENSSL_VERSION_NUMBER < 0x10000000L) + ++void engine::purge_error_state() { ++#if (OPENSSL_VERSION_NUMBER < 0x1010000fL && !defined(__APPLE__)) ++ // OpenSSL 1.1.0 introduced a thread local state storage mechanism. ++ // Versions prior sometimes had contention issues on global mutexes ++ // which protected thread local state. ++ // If we are compiled against a version without native thread local ++ // support, cache a pointer to this thread's error state, which we can ++ // access without contention. If that state requires no cleanup, ++ // we can avoid invoking OpenSSL's more expensive machinery. ++ const static thread_local ERR_STATE* es = ERR_get_state(); ++ if (es->bottom == es->top) { ++ return; ++ } ++#endif // (OPENSSL_VERSION_NUMBER < 0x1010000fL && !defined(__APPLE__)) ++ ::ERR_clear_error(); ++} ++ + engine::want engine::perform(int (engine::* op)(void*, std::size_t), + void* data, std::size_t length, asio::error_code& ec, + std::size_t* bytes_transferred) + { + std::size_t pending_output_before = ::BIO_ctrl_pending(ext_bio_); +- ::ERR_clear_error(); ++ purge_error_state(); + int result = (this->*op)(data, length); + int ssl_error = ::SSL_get_error(ssl_, result); + int sys_error = static_cast(::ERR_get_error()); +-- +2.24.1 + diff --git a/src/third_party/asio-master/patches/0004-SERVER-40393-Disable-SSL_MODE_RELEASE_BUFFERS-in-ASI.patch b/src/third_party/asio-master/patches/0004-SERVER-40393-Disable-SSL_MODE_RELEASE_BUFFERS-in-ASI.patch new file mode 100644 index 00000000000..a5b2cbee4fe --- /dev/null +++ b/src/third_party/asio-master/patches/0004-SERVER-40393-Disable-SSL_MODE_RELEASE_BUFFERS-in-ASI.patch @@ -0,0 +1,34 @@ +From 346f05a77bbc3a4d882d1e15b8f70cf5920a656b Mon Sep 17 00:00:00 2001 +From: Spencer Jackson +Date: Fri, 17 May 2019 13:08:29 -0400 +Subject: [PATCH] SERVER-40393 Disable SSL_MODE_RELEASE_BUFFERS in ASIO + +--- + asio/include/asio/ssl/detail/impl/engine.ipp | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/asio/include/asio/ssl/detail/impl/engine.ipp b/asio/include/asio/ssl/detail/impl/engine.ipp +index d001723b..96aeeb76 100644 +--- a/asio/include/asio/ssl/detail/impl/engine.ipp ++++ b/asio/include/asio/ssl/detail/impl/engine.ipp +@@ -44,13 +44,14 @@ engine::engine(SSL_CTX* context) + accept_mutex().init(); + #endif // (OPENSSL_VERSION_NUMBER < 0x10000000L) + + ::SSL_set_mode(ssl_, SSL_MODE_ENABLE_PARTIAL_WRITE); + ::SSL_set_mode(ssl_, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER); +-#if defined(SSL_MODE_RELEASE_BUFFERS) +- ::SSL_set_mode(ssl_, SSL_MODE_RELEASE_BUFFERS); +-#endif // defined(SSL_MODE_RELEASE_BUFFERS) ++ // SERVER-40393 - Disable SSL_MODE_RELEASE_BUFFERS in ASIO ++ //#if defined(SSL_MODE_RELEASE_BUFFERS) ++ //::SSL_set_mode(ssl_, SSL_MODE_RELEASE_BUFFERS); ++ //#endif // defined(SSL_MODE_RELEASE_BUFFERS) + + ::BIO* int_bio = 0; + ::BIO_new_bio_pair(&int_bio, 0, &ext_bio_, 0); + ::SSL_set_bio(ssl_, int_bio, int_bio); + } +-- +2.21.0 + -- cgit v1.2.1