]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MINOR: quic: fix decrement of half_open counter on qc alloc failure
authorAmaury Denoyelle <adenoyelle@haproxy.com>
Mon, 13 Nov 2023 09:55:30 +0000 (10:55 +0100)
committerAmaury Denoyelle <adenoyelle@haproxy.com>
Mon, 13 Nov 2023 10:16:41 +0000 (11:16 +0100)
Half open counter is used to comptabilize QUIC connections waiting for
address validation. It was recently reworked to adjust its scope. With
each decrement operation, a BUG_ON() was added to ensure the counter
never wraps.

This BUG_ON() could be triggered if an allocation fails for one of
quic_conn members in qc_new_conn(). This is because half open counter is
incremented at the end of qc_new_conn(). However, in case of alloc
failure, quic_conn_release() is called immediately to ensure the counter
is decremented if a connection is freed before peer address has been
validated.

To fix this, increment half open counter early in qc_new_conn() prior to
every quic_conn members allocations.

This issue was reproduced using -dMfail argument.

This issue has been introduced by
  commit 278808915b05bab1ff1e08e95fe32be22109719f
  MINOR: quic: reduce half open counters scope

No need to backport.

src/quic_conn.c

index 1c71344848e2fa4c7b969267ba86b9f38a6c0950..d3b89ab46ea558571cf7af3d15d962dca87138c6 100644 (file)
@@ -1289,6 +1289,18 @@ struct quic_conn *qc_new_conn(const struct quic_version *qv, int ipv4,
        qc->mux_state = QC_MUX_NULL;
        qc->err = quic_err_transport(QC_ERR_NO_ERROR);
 
+       /* If connection is instantiated due to an INITIAL packet with an
+        * already checked token, consider the peer address as validated.
+        */
+       if (token_odcid->len) {
+               TRACE_STATE("validate peer address due to initial token",
+                           QUIC_EV_CONN_INIT, qc);
+               qc->flags |= QUIC_FL_CONN_PEER_VALIDATED_ADDR;
+       }
+       else {
+               HA_ATOMIC_INC(&qc->prx_counters->half_open_conn);
+       }
+
        /* Now proceeds to allocation of qc members. */
        qc->rx.buf.area = pool_alloc(pool_head_quic_conn_rxbuf);
        if (!qc->rx.buf.area) {
@@ -1396,18 +1408,6 @@ struct quic_conn *qc_new_conn(const struct quic_version *qv, int ipv4,
        LIST_APPEND(&th_ctx->quic_conns, &qc->el_th_ctx);
        qc->qc_epoch = HA_ATOMIC_LOAD(&qc_epoch);
 
-       /* If connection is instantiated due to an INITIAL packet with an
-        * already checked token, consider the peer address as validated.
-        */
-       if (token_odcid->len) {
-               TRACE_STATE("validate peer address due to initial token",
-                           QUIC_EV_CONN_INIT, qc);
-               qc->flags |= QUIC_FL_CONN_PEER_VALIDATED_ADDR;
-       }
-       else {
-               HA_ATOMIC_INC(&qc->prx_counters->half_open_conn);
-       }
-
        TRACE_LEAVE(QUIC_EV_CONN_INIT, qc);
 
        return qc;