From 797c039a9884f69aae96286dcdf1ba633e5ebf81 Mon Sep 17 00:00:00 2001 From: Andrew Clayton Date: Tue, 29 Sep 2026 21:36:48 +0100 Subject: [PATCH] SSL: explicitly clear the session staging buffer Since 3d7304b52, sessions are serialized into the static buffer ngx_ssl_session_buffer, so the last cached, resumed, or proxied session remains in memory, master secret included, until overwritten. Clear the buffer on all exits that write to it. While here, the session id length check is moved before serialization, which removes an exit path with a populated buffer and a needless i2d_SSL_SESSION() call for sessions that are not cached. Note that sessions are still kept in shared memory until evicted. Assisted-by: opencode:claude-opus-5 Closes: https://github.com/nginx/nginx/issues/1736 --- src/event/ngx_event_openssl.c | 22 +++++++++++++------- src/http/ngx_http_upstream_round_robin.c | 7 +++++++ src/stream/ngx_stream_upstream_round_robin.c | 7 +++++++ 3 files changed, 28 insertions(+), 8 deletions(-) diff --git a/src/event/ngx_event_openssl.c b/src/event/ngx_event_openssl.c index 670dfefb0..8ba0122d4 100644 --- a/src/event/ngx_event_openssl.c +++ b/src/event/ngx_event_openssl.c @@ -4458,6 +4458,14 @@ ngx_ssl_new_session(ngx_ssl_conn_t *ssl_conn, ngx_ssl_session_t *sess) #endif + session_id = (u_char *) SSL_SESSION_get_id(sess, &session_id_length); + + /* do not cache sessions with too long session id */ + + if (session_id_length > 32) { + return 0; + } + len = i2d_SSL_SESSION(sess, NULL); /* do not cache too big session */ @@ -4469,14 +4477,6 @@ ngx_ssl_new_session(ngx_ssl_conn_t *ssl_conn, ngx_ssl_session_t *sess) p = ngx_ssl_session_buffer; i2d_SSL_SESSION(sess, &p); - session_id = (u_char *) SSL_SESSION_get_id(sess, &session_id_length); - - /* do not cache sessions with too long session id */ - - if (session_id_length > 32) { - return 0; - } - c = ngx_ssl_get_connection(ssl_conn); ssl_ctx = c->ssl->session_ctx; @@ -4551,6 +4551,8 @@ ngx_ssl_new_session(ngx_ssl_conn_t *ssl_conn, ngx_ssl_session_t *sess) ngx_shmtx_unlock(&shpool->mutex); + ngx_explicit_memzero(ngx_ssl_session_buffer, len); + return 0; failed: @@ -4561,6 +4563,8 @@ failed: ngx_shmtx_unlock(&shpool->mutex); + ngx_explicit_memzero(ngx_ssl_session_buffer, len); + if (cache->fail_time != ngx_time()) { cache->fail_time = ngx_time(); ngx_log_error(NGX_LOG_WARN, c->log, 0, @@ -4643,6 +4647,8 @@ ngx_ssl_get_cached_session(ngx_ssl_conn_t *ssl_conn, p = ngx_ssl_session_buffer; sess = d2i_SSL_SESSION(NULL, &p, slen); + ngx_explicit_memzero(ngx_ssl_session_buffer, slen); + return sess; } diff --git a/src/http/ngx_http_upstream_round_robin.c b/src/http/ngx_http_upstream_round_robin.c index 8f9bcfcf0..2e60f1a37 100644 --- a/src/http/ngx_http_upstream_round_robin.c +++ b/src/http/ngx_http_upstream_round_robin.c @@ -1142,6 +1142,8 @@ ngx_http_upstream_set_round_robin_peer_session(ngx_peer_connection_t *pc, p = ngx_ssl_session_buffer; ssl_session = d2i_SSL_SESSION(NULL, &p, len); + ngx_explicit_memzero(ngx_ssl_session_buffer, len); + rc = ngx_ssl_set_session(pc->connection, ssl_session); ngx_log_debug1(NGX_LOG_DEBUG_HTTP, pc->log, 0, @@ -1224,6 +1226,9 @@ ngx_http_upstream_save_round_robin_peer_session(ngx_peer_connection_t *pc, ngx_http_upstream_rr_peer_unlock(peers, peer); ngx_http_upstream_rr_peers_unlock(peers); + + ngx_explicit_memzero(ngx_ssl_session_buffer, len); + return; } @@ -1235,6 +1240,8 @@ ngx_http_upstream_save_round_robin_peer_session(ngx_peer_connection_t *pc, ngx_http_upstream_rr_peer_unlock(peers, peer); ngx_http_upstream_rr_peers_unlock(peers); + ngx_explicit_memzero(ngx_ssl_session_buffer, len); + return; } #endif diff --git a/src/stream/ngx_stream_upstream_round_robin.c b/src/stream/ngx_stream_upstream_round_robin.c index b4ea9a0af..2c8e54199 100644 --- a/src/stream/ngx_stream_upstream_round_robin.c +++ b/src/stream/ngx_stream_upstream_round_robin.c @@ -973,6 +973,8 @@ ngx_stream_upstream_set_round_robin_peer_session(ngx_peer_connection_t *pc, p = ngx_ssl_session_buffer; ssl_session = d2i_SSL_SESSION(NULL, &p, len); + ngx_explicit_memzero(ngx_ssl_session_buffer, len); + rc = ngx_ssl_set_session(pc->connection, ssl_session); ngx_log_debug1(NGX_LOG_DEBUG_STREAM, pc->log, 0, @@ -1055,6 +1057,9 @@ ngx_stream_upstream_save_round_robin_peer_session(ngx_peer_connection_t *pc, ngx_stream_upstream_rr_peer_unlock(peers, peer); ngx_stream_upstream_rr_peers_unlock(peers); + + ngx_explicit_memzero(ngx_ssl_session_buffer, len); + return; } @@ -1066,6 +1071,8 @@ ngx_stream_upstream_save_round_robin_peer_session(ngx_peer_connection_t *pc, ngx_stream_upstream_rr_peer_unlock(peers, peer); ngx_stream_upstream_rr_peers_unlock(peers); + ngx_explicit_memzero(ngx_ssl_session_buffer, len); + return; } #endif -- 2.47.3