This is an automated email from the ASF dual-hosted git repository. cmcfarlen pushed a commit to branch 10.0.x in repository https://gitbox.apache.org/repos/asf/trafficserver.git
commit 0e540a7b73886c9d527fa77b0a81f9b60925bea6 Author: Walt Karas <[email protected]> AuthorDate: Tue Jul 16 14:32:37 2024 -0400 Fix for OpenSSL 3.2+. (#11501) It seems BIO user data is no longer set to nullptr. (cherry picked from commit 6bf342ba362a42786b9efcb0d4d554f725643a8d) --- CMakeLists.txt | 3 + include/tscore/ink_config.h.cmake.in | 3 + src/iocore/net/BIO_fastopen.cc | 133 +++++++++++++++++++++++++++++++---- src/iocore/net/BIO_fastopen.h | 7 +- src/iocore/net/SSLNetVConnection.cc | 5 +- 5 files changed, 128 insertions(+), 23 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5b0a9ba594..0069e1b68f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -450,6 +450,9 @@ check_symbol_exists(BIO_meth_new "openssl/bio.h" HAVE_BIO_METH_NEW) check_symbol_exists(BIO_set_data "openssl/bio.h" HAVE_BIO_SET_DATA) check_symbol_exists(BIO_get_data "openssl/bio.h" HAVE_BIO_GET_DATA) check_symbol_exists(BIO_get_shutdown "openssl/bio.h" HAVE_BIO_GET_SHUTDOWN) +check_symbol_exists(BIO_get_ex_new_index "openssl/bio.h" HAVE_BIO_GET_EX_NEW_INDEX) +check_symbol_exists(BIO_get_ex_data "openssl/bio.h" HAVE_BIO_GET_EX_DATA) +check_symbol_exists(BIO_set_ex_data "openssl/bio.h" HAVE_BIO_SET_EX_DATA) check_symbol_exists(BIO_meth_get_ctrl "openssl/bio.h" HAVE_BIO_METH_GET_CTRL) check_symbol_exists(BIO_meth_get_create "openssl/bio.h" HAVE_BIO_METH_GET_CREATE) check_symbol_exists(BIO_meth_get_destroy "openssl/bio.h" HAVE_BIO_METH_GET_DESTROY) diff --git a/include/tscore/ink_config.h.cmake.in b/include/tscore/ink_config.h.cmake.in index b8f036457f..50e14e4019 100644 --- a/include/tscore/ink_config.h.cmake.in +++ b/include/tscore/ink_config.h.cmake.in @@ -80,6 +80,9 @@ #cmakedefine HAVE_BIO_SET_DATA 1 #cmakedefine HAVE_BIO_GET_DATA 1 #cmakedefine HAVE_BIO_GET_SHUTDOWN 1 +#cmakedefine HAVE_BIO_GET_EX_NEW_INDEX 1 +#cmakedefine HAVE_BIO_GET_EX_DATA 1 +#cmakedefine HAVE_BIO_SET_EX_DATA 1 #cmakedefine HAVE_BIO_METH_GET_CTRL 1 #cmakedefine HAVE_BIO_METH_GET_CREATE 1 #cmakedefine HAVE_BIO_METH_GET_DESTROY 1 diff --git a/src/iocore/net/BIO_fastopen.cc b/src/iocore/net/BIO_fastopen.cc index ac2a9e38b7..fd9ea9dd9c 100644 --- a/src/iocore/net/BIO_fastopen.cc +++ b/src/iocore/net/BIO_fastopen.cc @@ -21,12 +21,116 @@ * limitations under the License. */ +#include <openssl/opensslv.h> + #include "P_Net.h" #include "iocore/eventsystem/SocketManager.h" #include "tscore/ink_assert.h" +#include "tscore/ink_config.h" #include "BIO_fastopen.h" +#if defined(BORINGLIKE) +#error +#elif defined(OPENSSL_IS_BORINGSSL) || defined(OPENSSL_IS_AWSLC) +#define BORINGLIKE 1 +#else +#define BORINGLIKE 0 +#endif + +namespace +{ + +#if defined(HAVE_BIO_GET_EX_NEW_INDEX) && defined(HAVE_BIO_GET_EX_DATA) && defined(HAVE_BIO_SET_EX_DATA) + +class ExData +{ +public: + // Pseudo-namespace + ExData() = delete; + + static int + idx() + { + static int idx_ = []() -> int { + int i = BIO_get_ex_new_index(0, nullptr, _new, _dup, _free); + ink_release_assert(i >= 0); + return i; + }(); + return idx_; + } + +private: +#if BORINGLIKE + static constexpr CRYPTO_EX_unused *_new{nullptr}; +#else + static void + _new(void * /* parent */, void * /* ptr */, CRYPTO_EX_DATA *ad, int idx_, long /* argl */, void * /* argp */) + { + ink_release_assert(CRYPTO_set_ex_data(ad, idx_, nullptr) == 1); + } +#endif + +#if BORINGLIKE + static void + _free(void * /* parent */, void * /* ptr */, CRYPTO_EX_DATA * /* ad */, int /* idx_ */, long /* argl */, void * /* argp */) + { + } +#else + static void + _free(void * /* parent */, void * /* ptr */, CRYPTO_EX_DATA *ad, int idx_, long /* argl */, void * /* argp */) + { + ink_release_assert(CRYPTO_set_ex_data(ad, idx_, nullptr) == 1); + } +#endif + +#if BORINGLIKE || (OPENSSL_VERSION_MAJOR >= 3) + using _Type_from_d = void **; +#else + using _Type_from_d = void *; +#endif + + static int + _dup(CRYPTO_EX_DATA * /* to */, const CRYPTO_EX_DATA * /* from */, _Type_from_d /* from_d */, int /* idx */, long /* argl */, + void * /* argp */) + { + ink_assert(false); + return 0; + } +}; + +inline void +set_dest_addr_for_bio(BIO *b, void *dest_addr) +{ + ink_assert(BIO_set_ex_data(b, ExData::idx(), dest_addr) == 1); +} + +inline void * +get_dest_addr_for_bio(BIO *b) +{ + return BIO_get_ex_data(b, ExData::idx()); +} + +#else // no BIO ex data in SSL library + +// Fall back on the krufty way this was done using older SSL libraries. + +inline void +set_dest_addr_for_bio(BIO *b, void *dest_addr) +{ + BIO_set_data(b, dest_addr); +} + +inline void * +get_dest_addr_for_bio(BIO *b) +{ + return BIO_get_data(b); +} + +#endif + +} // end anonymous namespace + // For BoringSSL, which for some reason doesn't have this function. // (In BoringSSL, sock_read() and sock_write() use the internal // bio_fd_non_fatal_error() instead.) #1437 @@ -113,20 +217,20 @@ fastopen_bwrite(BIO *bio, const char *in, int insz) int fd = BIO_get_fd(bio, nullptr); ink_assert(fd != NO_FD); - if (BIO_get_data(bio)) { + void *dst_void = get_dest_addr_for_bio(bio); + if (dst_void) { + auto dst = static_cast<sockaddr *>(dst_void); // On the first write only, make a TFO request if TFO is enabled. // The best documentation on the behavior of the Linux API is in // RFC 7413. If we get EINPROGRESS it means that the SYN has been // sent without data and we should retry. - const sockaddr *dst = reinterpret_cast<const sockaddr *>(BIO_get_data(bio)); - Metrics::Counter::increment(net_rsb.fastopen_attempts); err = SocketManager::sendto(fd, (void *)in, insz, MSG_FASTOPEN, dst, ats_ip_size(dst)); if (err >= 0) { Metrics::Counter::increment(net_rsb.fastopen_successes); } - BIO_set_data(bio, nullptr); + set_dest_addr_for_bio(bio, nullptr); } else { err = SocketManager::write(fd, (void *)in, insz); } @@ -164,21 +268,14 @@ fastopen_bread(BIO *bio, char *out, int outsz) return err < 0 ? -1 : err; } +#ifndef HAVE_BIO_METH_NEW + static long fastopen_ctrl(BIO *bio, int cmd, long larg, void *ptr) { - switch (cmd) { - case BIO_C_SET_CONNECT: - // We only support BIO_set_conn_address(), which sets a sockaddr. - ink_assert(larg == 2); - BIO_set_data(bio, ptr); - return 0; - } - return BIO_meth_get_ctrl(const_cast<BIO_METHOD *>(BIO_s_socket()))(bio, cmd, larg, ptr); } -#ifndef HAVE_BIO_METH_NEW static const BIO_METHOD fastopen_methods[] = { { .type = BIO_TYPE_SOCKET, @@ -193,12 +290,12 @@ static const BIO_METHOD fastopen_methods[] = { .callback_ctrl = nullptr, } }; -#else +#else // defined(HAVE_BIO_METH_NEW) static const BIO_METHOD *fastopen_methods = [] { BIO_METHOD *methods = BIO_meth_new(BIO_TYPE_SOCKET, "fastopen"); BIO_meth_set_write(methods, fastopen_bwrite); BIO_meth_set_read(methods, fastopen_bread); - BIO_meth_set_ctrl(methods, fastopen_ctrl); + BIO_meth_set_ctrl(methods, BIO_meth_get_ctrl(const_cast<BIO_METHOD *>(BIO_s_socket()))); BIO_meth_set_create(methods, fastopen_create); BIO_meth_set_destroy(methods, fastopen_destroy); return methods; @@ -210,3 +307,9 @@ BIO_s_fastopen() { return fastopen_methods; } + +void +BIO_fastopen_set_dest_addr(BIO *bio, const sockaddr *dest_addr) +{ + set_dest_addr_for_bio(bio, const_cast<sockaddr *>(dest_addr)); +} diff --git a/src/iocore/net/BIO_fastopen.h b/src/iocore/net/BIO_fastopen.h index ce42e3be42..b949953daa 100644 --- a/src/iocore/net/BIO_fastopen.h +++ b/src/iocore/net/BIO_fastopen.h @@ -29,8 +29,5 @@ // Return a BIO_METHOD for a socket BIO that implements TCP Fast Open. const BIO_METHOD *BIO_s_fastopen(); -// OpenSSL 1.0.2h has BIO_set_conn_ip(), but master has BIO_set_conn_address(). Use -// the API from master since it makes more sense. -#if !defined(BIO_set_conn_address) -#define BIO_set_conn_address(b, addr) BIO_ctrl(b, BIO_C_SET_CONNECT, 2, (char *)addr) -#endif +// Set destination address for a BIO for a fastopen TCP socket where the local host is the client. +void BIO_fastopen_set_dest_addr(BIO *bio, const sockaddr *dest_addr); diff --git a/src/iocore/net/SSLNetVConnection.cc b/src/iocore/net/SSLNetVConnection.cc index ca89894be0..5ebb705f0e 100644 --- a/src/iocore/net/SSLNetVConnection.cc +++ b/src/iocore/net/SSLNetVConnection.cc @@ -212,9 +212,8 @@ SSLNetVConnection::_make_ssl_connection(SSL_CTX *ctx) BIO *bio = BIO_new(const_cast<BIO_METHOD *>(BIO_s_fastopen())); BIO_set_fd(bio, this->get_socket(), BIO_NOCLOSE); - if (this->options.f_tcp_fastopen) { - BIO_set_conn_address(bio, this->get_remote_addr()); - } + BIO_fastopen_set_dest_addr(bio, + this->options.f_tcp_fastopen ? this->get_remote_addr() : static_cast<const sockaddr *>(nullptr)); SSL_set_bio(ssl, bio, bio); } else {
