]> git.kaiwu.me - haproxy.git/commitdiff
BUG/MINOR: mux_quic: report conn error on RESET_STREAM fctl violation
authorAmaury Denoyelle <adenoyelle@haproxy.com>
Wed, 23 Sep 2026 13:28:29 +0000 (15:28 +0200)
committerAmaury Denoyelle <adenoyelle@haproxy.com>
Wed, 7 Oct 2026 08:21:48 +0000 (10:21 +0200)
When a RESET_STREAM is received, its announced final size must be taken
into account in the connection flow control.

This patch is a prerequisite prior to implement this accounting. It adds
the mandatory check of the final size field to ensure it does not
violate either the stream or the connection flow control.

In case of invalid value, the connection is closed with
FLOW_CONTROL_ERROR.

This must be backported up to 2.8, after a period of observation.

src/mux_quic.c

index b9ae11551216f2689bde91390009836dab5a1e1e..86585999c721bb74f68a58b634823d5edcf64cae 100644 (file)
@@ -2321,6 +2321,7 @@ int qcc_recv_reset_stream(struct qcc *qcc, uint64_t id, uint64_t err, uint64_t f
        struct qcs *qcs;
        struct qc_stream_rxbuf *b;
        int prev_glitches = qcc->glitches;
+       uint64_t to_consume;
 
        TRACE_ENTER(QMUX_EV_QCC_RECV, qcc->conn);
 
@@ -2362,12 +2363,28 @@ int qcc_recv_reset_stream(struct qcc *qcc, uint64_t id, uint64_t err, uint64_t f
 
        if (qcs->rx.offset_max > final_size ||
            ((qcs->flags & QC_SF_SIZE_KNOWN) && qcs->rx.offset_max != final_size)) {
-               TRACE_ERROR("final size error on RESET_STREAM", QMUX_EV_QCC_RECV|QMUX_EV_QCS_RECV, qcc->conn, qcs);
+               TRACE_ERROR("final size error on RESET_STREAM",
+                           QMUX_EV_QCC_RECV|QMUX_EV_QCS_RECV|QMUX_EV_PROTO_ERR, qcc->conn, qcs);
                qcc_set_error(qcc, QC_ERR_FINAL_SIZE_ERROR, 0,
                              muxc_tevt_type_proto_err);
                goto err;
        }
 
+       /* Discarded data to account for in connection flow control. */
+       to_consume = final_size - qcs->rx.offset;
+
+       /* Ensure final size respects the current stream and connection flow control limits. */
+       if (final_size > qcs->rx.msd ||
+           qcc->lfctl.offsets_recv + to_consume > qcc->lfctl.md) {
+               TRACE_ERROR("flow control violation on RESET_STREAM final size",
+                           QMUX_EV_QCC_RECV|QMUX_EV_QCS_RECV|QMUX_EV_PROTO_ERR, qcc->conn, qcs);
+               qcc_set_error(qcc, QC_ERR_FLOW_CONTROL_ERROR, 0,
+                             muxc_tevt_type_proto_err);
+               goto err;
+       }
+
+       qcc->lfctl.offsets_recv += to_consume;
+
        qcs->flags |= QC_SF_SIZE_KNOWN|QC_SF_RECV_RESET;
        qcs_close_remote(qcs);
        /* Wakeup tasklet if QCS inserted in purge list. May happen after remote closure. */