From 2afa9de06b6bd2ee855acdfce7325e110ed8d2d3 Mon Sep 17 00:00:00 2001 From: Bryan Call Date: Sun, 22 Mar 2026 20:38:30 -0700 Subject: [PATCH 1/3] Fix memory leaks in SSLConfig: BIO, session cache, ocsp_user_agent Fix three leak categories in SSLConfig: - Clear BIO_FLAGS_MEM_RDONLY before BIO_free so internal BUF_MEM structures are properly released - Delete existing session_cache/origin_sess_cache before allocating new ones in initialize() - Free ssl_ocsp_user_agent before overwriting with new value --- src/iocore/net/SSLConfig.cc | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/iocore/net/SSLConfig.cc b/src/iocore/net/SSLConfig.cc index 6aaf8c2374b..9d488725f32 100644 --- a/src/iocore/net/SSLConfig.cc +++ b/src/iocore/net/SSLConfig.cc @@ -454,6 +454,7 @@ SSLConfigParams::initialize() SSLConfigParams::origin_session_cache_size = ssl_origin_session_cache_size; if (ssl_origin_session_cache == 1 && ssl_origin_session_cache_size > 0) { + delete origin_sess_cache; origin_sess_cache = new SSLOriginSessionCache(); } @@ -472,6 +473,7 @@ SSLConfigParams::initialize() set_paths_helper(ssl_ocsp_response_path, nullptr, &ssl_ocsp_response_path_only, nullptr); } if (auto rec_str{RecGetRecordStringAlloc("proxy.config.http.request_via_str")}; rec_str) { + ats_free(ssl_ocsp_user_agent); ssl_ocsp_user_agent = ats_stringdup(rec_str); } @@ -861,6 +863,11 @@ SSLTicketParams::cleanup() void cleanup_bio(BIO *&biop) { + // BIO_new_mem_buf sets BIO_FLAGS_MEM_RDONLY which prevents BIO_free from + // cleaning up internal BUF_MEM structures. Clear this flag so BIO_free + // properly releases them. BIO_NOCLOSE ensures the external data buffer + // (owned by the caller's std::string) is not freed. + BIO_clear_flags(biop, BIO_FLAGS_MEM_RDONLY); #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunused-value" BIO_set_close(biop, BIO_NOCLOSE); From f7920997509fd0d2e0e04c6b88663beddde892f6 Mon Sep 17 00:00:00 2001 From: Bryan Call Date: Sun, 22 Mar 2026 21:35:23 -0700 Subject: [PATCH 2/3] Fix memory leak in SSLOriginSessionCache destructor The destructor was empty, leaking all SSLOriginSession objects still held in the CountQueue and map when the cache was destroyed. Pop and delete every queued node before the map is implicitly destroyed. --- src/iocore/net/SSLSessionCache.cc | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/iocore/net/SSLSessionCache.cc b/src/iocore/net/SSLSessionCache.cc index 9f6c52fa949..2a68f268683 100644 --- a/src/iocore/net/SSLSessionCache.cc +++ b/src/iocore/net/SSLSessionCache.cc @@ -43,7 +43,13 @@ SSLSessDeleter(SSL_SESSION *_p) SSLOriginSessionCache::SSLOriginSessionCache() {} -SSLOriginSessionCache::~SSLOriginSessionCache() {} +SSLOriginSessionCache::~SSLOriginSessionCache() +{ + while (auto *node = orig_sess_que.pop()) { + delete node; + } + orig_sess_map.clear(); +} void SSLOriginSessionCache::insert_session(const std::string &lookup_key, SSL_SESSION *sess, SSL *ssl) From 2003438f5feabd08137db9e2b2fa4efbd0002c2a Mon Sep 17 00:00:00 2001 From: Bryan Call Date: Thu, 26 Mar 2026 22:40:56 -0700 Subject: [PATCH 3/3] Allocate origin session cache once instead of delete/new on reload The cache self-sizes on insert via the static origin_session_cache_size, so recreating it is unnecessary and unsafe (concurrent TLS handshakes hold bare pointers to the global). Allocate once; let entries age out naturally when the configured size shrinks. --- src/iocore/net/SSLConfig.cc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/iocore/net/SSLConfig.cc b/src/iocore/net/SSLConfig.cc index 9d488725f32..bbf80592399 100644 --- a/src/iocore/net/SSLConfig.cc +++ b/src/iocore/net/SSLConfig.cc @@ -453,8 +453,7 @@ SSLConfigParams::initialize() SSLConfigParams::origin_session_cache = ssl_origin_session_cache; SSLConfigParams::origin_session_cache_size = ssl_origin_session_cache_size; - if (ssl_origin_session_cache == 1 && ssl_origin_session_cache_size > 0) { - delete origin_sess_cache; + if (ssl_origin_session_cache == 1 && ssl_origin_session_cache_size > 0 && origin_sess_cache == nullptr) { origin_sess_cache = new SSLOriginSessionCache(); }