]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MEDIUM: quic-be/ssl_sock: TLS callback called without connection
authorFrederic Lecaille <flecaille@haproxy.com>
Thu, 20 Nov 2025 10:10:56 +0000 (11:10 +0100)
committerFrederic Lecaille <flecaille@haproxy.com>
Thu, 20 Nov 2025 10:36:57 +0000 (11:36 +0100)
Contrary to TCP, QUIC does not SSL_free() its SSL *  object when its ->close()
XPRT callback is called. This has as side effect to trigger some BUG_ON(!conn)
with <conn> the connection from TLS callbacks registered at configuration
parsing time, so after this <conn> have been released.

This is the case for instance with ssl_sock_srv_verifycbk() whose role is to
add some checks to the built-in server certificate verification process.

This patch prevents the pointer to <conn> dereferencing inside several callbacks
shared between TCP and QUIC.

Thank you to @InputOutputZ for its report in GH #3188.

As the QUIC backend feature arrived with the current 3.3 dev, no need to backport.

src/ssl_sock.c

index 40d5da29e99568c6f740f34ea7e1bbabc33a2835..93c58ee7adb0bd1b56adec1a1e2d967fdf794764 100644 (file)
@@ -1638,7 +1638,12 @@ static void ssl_sock_infocbk(const SSL *ssl, int where, int ret)
        (void)conn;
 
        conn = ssl_sock_get_conn(ssl, &ctx);
-       /* must never happen */
+       /* The connection be NULL only for QUIC which does not free its SSL object
+        * as this done for TCP.
+        */
+       if (!conn)
+               return;
+
        BUG_ON(!ctx);
 #ifndef SSL_OP_NO_RENEGOTIATION
        /* Please note that BoringSSL defines this macro to zero so don't
@@ -2148,6 +2153,12 @@ static __maybe_unused void ssl_sock_msgcbk(int write_p, int version, int content
        struct connection *conn = ssl_sock_get_conn(ssl, NULL);
        struct ssl_sock_msg_callback *cbk;
 
+       /* The connection be NULL only for QUIC which does not free its SSL object
+        * as this done for TCP.
+        */
+       if (!conn)
+               return;
+
        /* Try to call all callback functions that were registered by using
         * ssl_sock_register_msg_callback().
         */
@@ -4167,7 +4178,12 @@ static int ssl_sess_new_srv_cb(SSL *ssl, SSL_SESSION *sess)
        struct server *s;
        uint old_tid;
 
-       BUG_ON(!conn);
+       /* The connection may be NULL only for QUIC which does not free its SSL object
+        * as this done for TCP.
+        */
+       if (!conn)
+               return 0;
+
        s = __objt_server(conn->target);
 
        /* RWLOCK: only read lock the SSL cache even when writing in it because there is
@@ -4877,7 +4893,12 @@ static int ssl_sock_srv_verifycbk(int ok, X509_STORE_CTX *ctx)
 
        ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
        conn = ssl_sock_get_conn(ssl, NULL);
-       BUG_ON(!conn);
+       /* The connection may be NULL only for QUIC which does not free its SSL object
+        * as this done for TCP.
+        */
+       if (!conn)
+               return 0;
+
        ssl_ctx = __conn_get_ssl_sock_ctx(conn);
 
        /* We're checking if the provided hostnames match the desired one. The