]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MINOR: mux-quic: fix free on qcs-new fail alloc
authorAmaury Denoyelle <adenoyelle@haproxy.com>
Wed, 11 Oct 2023 15:32:04 +0000 (17:32 +0200)
committerAmaury Denoyelle <adenoyelle@haproxy.com>
Fri, 13 Oct 2023 06:52:29 +0000 (08:52 +0200)
qcs_new() allocates several elements in intermediary steps. All elements
must first be properly initialized to be able to free qcs instance in
case of an intermediary failure.

Previously, qc_stream_desc allocation was done in the middle of
qcs_new() before some elements initializations. In case this fails, a
crash can happened as some elements are left uninitialized.

To fix this, move qc_stream_desc allocation at the end of qcs_new().
This ensures that all qcs elements are initialized first.

This should be backported up to 2.6.

src/mux_quic.c

index 5be382fab4d0a0383f86bae1349eb8c4ac78a29f..429b22f9cbcdc4df27d68eea0dd0529d26a8cc40 100644 (file)
@@ -112,16 +112,6 @@ static struct qcs *qcs_new(struct qcc *qcc, uint64_t id, enum qcs_type type)
        qcs->id = qcs->by_id.key = id;
        eb64_insert(&qcc->streams_by_id, &qcs->by_id);
 
-       /* Allocate transport layer stream descriptor. Only needed for TX. */
-       if (!quic_stream_is_uni(id) || !quic_stream_is_remote(qcc, id)) {
-               struct quic_conn *qc = qcc->conn->handle.qc;
-               qcs->stream = qc_stream_desc_new(id, type, qcs, qc);
-               if (!qcs->stream) {
-                       TRACE_ERROR("qc_stream_desc alloc failure", QMUX_EV_QCS_NEW, qcc->conn, qcs);
-                       goto err;
-               }
-       }
-
        /* If stream is local, use peer remote-limit, or else the opposite. */
        if (quic_stream_is_bidi(id)) {
                qcs->tx.msd = quic_stream_is_local(qcc, id) ? qcc->rfctl.msd_bidi_r :
@@ -158,6 +148,16 @@ static struct qcs *qcs_new(struct qcc *qcc, uint64_t id, enum qcs_type type)
 
        qcs->err = 0;
 
+       /* Allocate transport layer stream descriptor. Only needed for TX. */
+       if (!quic_stream_is_uni(id) || !quic_stream_is_remote(qcc, id)) {
+               struct quic_conn *qc = qcc->conn->handle.qc;
+               qcs->stream = qc_stream_desc_new(id, type, qcs, qc);
+               if (!qcs->stream) {
+                       TRACE_ERROR("qc_stream_desc alloc failure", QMUX_EV_QCS_NEW, qcc->conn, qcs);
+                       goto err;
+               }
+       }
+
        if (qcc->app_ops->attach && qcc->app_ops->attach(qcs, qcc->ctx)) {
                TRACE_ERROR("app proto failure", QMUX_EV_QCS_NEW, qcc->conn, qcs);
                goto err;