]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MINOR: quic: Possible crash when issuing "show fd/sess" CLI commands
authorFrédéric Lécaille <flecaille@haproxy.com>
Fri, 11 Aug 2023 09:21:31 +0000 (11:21 +0200)
committerFrédéric Lécaille <flecaille@haproxy.com>
Fri, 11 Aug 2023 09:21:31 +0000 (11:21 +0200)
->xprt_ctx (struct ssl_sock_ctx) and ->conn (struct connection) must be kept
by the remaining QUIC connection object (struct quic_cc_conn) after having
release the previous one (struct quic_conn) to allow "show fd/sess" commands
to be functional without causing haproxy crashes.

No need to backport.

include/haproxy/quic_conn-t.h
src/quic_conn.c

index a8472add50b506703534ec4239af6481cc3c353a..92d1323cad2b4307d368c006ecb077a3f7f330fa 100644 (file)
@@ -495,6 +495,11 @@ struct quic_conn_cntrs {
         /* Idle timer task */                                                  \
         struct task *idle_timer_task;                                          \
         unsigned int idle_expire;                                              \
+        struct ssl_sock_ctx *xprt_ctx;                                         \
+        /* Used only to reach the tasklet for the I/O handler from this        \
+         * quic_conn object.                                                   \
+         */                                                                    \
+        struct connection *conn;                                               \
     }
 
 struct quic_conn {
@@ -531,14 +536,10 @@ struct quic_conn {
        /* List of packet number spaces attached to this connection */
        struct list pktns_list;
 
-       struct ssl_sock_ctx *xprt_ctx;
 #ifdef USE_QUIC_OPENSSL_COMPAT
        struct quic_openssl_compat openssl_compat;
 #endif
 
-       /* Used only to reach the tasklet for the I/O handler from this quic_conn object. */
-       struct connection *conn;
-
        struct {
                /* Transport parameters sent by the peer */
                struct quic_transport_params params;
index 6751b360e9a1fe3d0589af8e75cc9f14e9cae24a..d0ffc992c9cc3191a8b9e911c8a6e4fe4b381ddd 100644 (file)
@@ -756,6 +756,8 @@ static void quic_release_cc_conn(struct quic_cc_conn *cc_qc)
 {
        struct quic_conn *qc = (struct quic_conn *)cc_qc;
 
+       TRACE_ENTER(QUIC_EV_CONN_IO_CB, cc_qc);
+
        if (qc_test_fd(qc))
                _HA_ATOMIC_DEC(&jobs);
 
@@ -769,7 +771,11 @@ static void quic_release_cc_conn(struct quic_cc_conn *cc_qc)
        cc_qc->cids = NULL;
        pool_free(pool_head_quic_cc_buf, cc_qc->cc_buf_area);
        cc_qc->cc_buf_area = NULL;
+       /* free the SSL sock context */
+       qc_free_ssl_sock_ctx(&cc_qc->xprt_ctx);
        pool_free(pool_head_quic_cc_conn, cc_qc);
+
+       TRACE_ENTER(QUIC_EV_CONN_IO_CB);
 }
 
 /* QUIC connection packet handler task used when in "closing connection" state. */
@@ -872,8 +878,15 @@ static struct quic_cc_conn *qc_new_cc_conn(struct quic_conn *qc)
        cc_qc->idle_timer_task->context = cc_qc;
        cc_qc->idle_expire = qc->idle_expire;
 
+       cc_qc->xprt_ctx = qc->xprt_ctx;
+       qc->xprt_ctx = NULL;
+       cc_qc->conn = qc->conn;
+       qc->conn = NULL;
+
        cc_qc->cc_buf_area = qc->tx.cc_buf_area;
        cc_qc->cc_dgram_len = qc->tx.cc_dgram_len;
+       TRACE_PRINTF(TRACE_LEVEL_PROTO, QUIC_EV_CONN_IO_CB, qc, 0, 0, 0,
+                    "switch qc@%p to cc_qc@%p", qc, cc_qc);
 
        return cc_qc;
 }
@@ -1418,6 +1431,8 @@ void quic_conn_release(struct quic_conn *qc)
                qc->cids = NULL;
                pool_free(pool_head_quic_cc_buf, qc->tx.cc_buf_area);
                qc->tx.cc_buf_area = NULL;
+               /* free the SSL sock context */
+               qc_free_ssl_sock_ctx(&qc->xprt_ctx);
        }
 
        /* in the unlikely (but possible) case the connection was just added to
@@ -1449,9 +1464,6 @@ void quic_conn_release(struct quic_conn *qc)
        task_destroy(qc->timer_task);
        qc->timer_task = NULL;
 
-       /* free the SSL sock context */
-       qc_free_ssl_sock_ctx(&qc->xprt_ctx);
-
        quic_tls_ku_free(qc);
        if (qc->ael) {
                struct quic_tls_ctx *actx = &qc->ael->tls_ctx;