Commit 0a72e6ae74 for openssl.org

commit 0a72e6ae74a6d32977ac53cbf314f414c08b327b
Author: Bernd Edlinger <bernd.edlinger@hotmail.de>
Date:   Mon Sep 22 16:23:47 2025 +0200

    Fix error handling in SSL_CTX_add_session

    An out-of-memory error in lh_SSL_SESSION_insert
    could trigger various use-after-free errors.

    Fixes #28632

    Reviewed-by: Eugene Syromiatnikov <esyr@openssl.org>
    Reviewed-by: Nikola Pajkovsky <nikolap@openssl.org>
    Reviewed-by: Neil Horman <nhorman@openssl.org>
    MergeDate: Thu Mar 12 17:51:38 2026
    (Merged from https://github.com/openssl/openssl/pull/28636)

diff --git a/ssl/ssl_sess.c b/ssl/ssl_sess.c
index b911d6cffb..82d5d74352 100644
--- a/ssl/ssl_sess.c
+++ b/ssl/ssl_sess.c
@@ -788,9 +788,9 @@ int SSL_CTX_add_session(SSL_CTX *ctx, SSL_SESSION *c)
                     ssl_tsan_counter(ctx, &ctx->stats.sess_cache_full);
             }
         }
-    }

-    SSL_SESSION_list_add(ctx, c);
+        SSL_SESSION_list_add(ctx, c);
+    }

     if (s != NULL) {
         /*
diff --git a/test/sslapitest.c b/test/sslapitest.c
index f708b8a9c4..f93c58ef7c 100644
--- a/test/sslapitest.c
+++ b/test/sslapitest.c
@@ -10227,6 +10227,7 @@ static int test_session_cache_overflow(int idx)
     SSL *serverssl = NULL, *clientssl = NULL;
     int testresult = 0;
     SSL_SESSION *sess = NULL;
+    int references;

 #ifdef OSSL_NO_USABLE_TLS1_3
     /* If no TLSv1.3 available then do nothing in this case */
@@ -10300,6 +10301,15 @@ static int test_session_cache_overflow(int idx)
     get_sess_val = SSL_get_session(serverssl);
     if (!TEST_ptr(get_sess_val))
         goto end;
+    /*
+     * Normally the session is also stored in the cache, thus we have more than
+     * one reference, but due to an out-of-memory error it can happen that this
+     * is the only reference, and in that case the SSL_free(serverssl) below
+     * would free the get_sess_val, causing a use-after-free error.
+     */
+    if (!TEST_true(CRYPTO_GET_REF(&get_sess_val->references, &references))
+            || !TEST_int_ge(references, 2))
+        goto end;
     sess = SSL_get1_session(clientssl);
     if (!TEST_ptr(sess))
         goto end;