]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MEDIUM: mux-quic: fix crash on H3 SETTINGS emission
authorAmaury Denoyelle <adenoyelle@haproxy.com>
Wed, 25 Jan 2023 16:44:36 +0000 (17:44 +0100)
committerAmaury Denoyelle <adenoyelle@haproxy.com>
Wed, 25 Jan 2023 17:01:18 +0000 (18:01 +0100)
A major regression was introduced by following patch
    commit 71fd03632fff43f11cebc6ff4974723c9dc81c67
    MINOR: mux-quic/h3: send SETTINGS as soon as transport is ready

H3 finalize operation is now called at an early stage in the middle of
qc_init(). However, some qcc members are not yet initialized. In
particular the stream tree which will cause a crash when H3 control
stream will be accessed.

To fix this, qcc_install_app_ops() has been delayed at the end of
qc_init(). This ensures that qcc is properly initialized when app_ops
operation are used.

This must be backported wherever above patch is. For the record, it has
been tagged up to 2.7.

src/mux_quic.c

index b7b843e357e875f71e6b9fbca538f5575cde3fab..401ccc0c10ff0385cc046338679f35ff23999dcb 100644 (file)
@@ -875,13 +875,13 @@ int qcc_install_app_ops(struct qcc *qcc, const struct qcc_app_ops *app_ops)
 {
        TRACE_ENTER(QMUX_EV_QCC_NEW, qcc->conn);
 
-       qcc->app_ops = app_ops;
-       if (qcc->app_ops->init && !qcc->app_ops->init(qcc)) {
+       if (app_ops->init && !app_ops->init(qcc)) {
                TRACE_ERROR("app ops init error", QMUX_EV_QCC_NEW, qcc->conn);
                goto err;
        }
 
        TRACE_PROTO("application layer initialized", QMUX_EV_QCC_NEW, qcc->conn);
+       qcc->app_ops = app_ops;
 
        /* RFC 9114 7.2.4.2. Initialization
         *
@@ -2100,12 +2100,6 @@ static int qc_init(struct connection *conn, struct proxy *prx,
        qcc->flags = 0;
 
        qcc->app_ops = NULL;
-       if (qcc_install_app_ops(qcc, conn->handle.qc->app_ops)) {
-               TRACE_PROTO("Cannot install app layer", QMUX_EV_QCC_NEW, qcc->conn);
-               /* prepare a CONNECTION_CLOSE frame */
-               quic_set_connection_close(conn->handle.qc, quic_err_transport(QC_ERR_APPLICATION_ERROR));
-               goto fail_no_tasklet;
-       }
 
        qcc->streams_by_id = EB_ROOT_UNIQUE;
 
@@ -2205,17 +2199,26 @@ static int qc_init(struct connection *conn, struct proxy *prx,
        }
 
        HA_ATOMIC_STORE(&conn->handle.qc->qcc, qcc);
+
+       if (qcc_install_app_ops(qcc, conn->handle.qc->app_ops)) {
+               TRACE_PROTO("Cannot install app layer", QMUX_EV_QCC_NEW, qcc->conn);
+               /* prepare a CONNECTION_CLOSE frame */
+               quic_set_connection_close(conn->handle.qc, quic_err_transport(QC_ERR_APPLICATION_ERROR));
+               goto fail_install_app_ops;
+       }
+
        /* init read cycle */
        tasklet_wakeup(qcc->wait_event.tasklet);
 
        TRACE_LEAVE(QMUX_EV_QCC_NEW, qcc->conn);
        return 0;
 
+ fail_install_app_ops:
+       if (qcc->app_ops && qcc->app_ops->release)
+               qcc->app_ops->release(qcc->ctx);
  fail_no_timeout_task:
        tasklet_free(qcc->wait_event.tasklet);
  fail_no_tasklet:
-       if (qcc->app_ops && qcc->app_ops->release)
-               qcc->app_ops->release(qcc->ctx);
        pool_free(pool_head_qcc, qcc);
  fail_no_qcc:
        TRACE_LEAVE(QMUX_EV_QCC_NEW);