]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MEDIUM: mux-quic: prevent BUG_ON() on aborted uni stream close quic-interop flx04/quic-interop
authorAmaury Denoyelle <adenoyelle@haproxy.com>
Tue, 20 Jan 2026 18:00:37 +0000 (19:00 +0100)
committerAmaury Denoyelle <adenoyelle@haproxy.com>
Wed, 21 Jan 2026 13:01:12 +0000 (14:01 +0100)
When a QCS instance is fully closed on qcs_close_remote() invokation, it
is moved into purg_list for later cleanup. This reuses <el_send> list
element, so a BUG_ON() ensures that QCS is not already present in
send_list.

This code is safe for bidirectional streams, as local channel is only
closed after FIN or RESET_STREAM emission completion, so such QCS won't
be present in the send_list on full closure.

However, things are different for remote uni streams. As such streams do
not have any local channel, qcs_close_remote() will always proceed to
full closure. Most of the time this is fine, but the aformentionned
BUG_ON() could be triggered if emission is required on a remote uni
stream : this only happens after read was aborted and a STOP_SENDING
frame is prepared.

Fix this by adding an extra operation in qcs_close_remote() : on full
close, STOP_SENDING is cancelled if it was prepared and the QCS instance
is removed from send_list. This is safe as STOP_SENDING is unnecessary
after the remote channel is closed. This operation is performed before
purg_list insertion which prevents the BUG_ON() crash issue.

This patch must be backported up to 3.1.

src/mux_quic.c

index 1f11c4d59af762fd92239fb351c84544e692fc2f..2db2e3320eaf4149f74886adc2c3c5ed40230ff7 100644 (file)
@@ -462,6 +462,13 @@ static void qcs_close_remote(struct qcs *qcs)
                qcs->st = QC_SS_CLO;
        }
 
+       /* Cancel STOP_SENDING emission as it is now unneeded. */
+       if (qcs->st == QC_SS_CLO && (qcs->flags & QC_SF_TO_STOP_SENDING)) {
+               qcs->flags &= ~QC_SF_TO_STOP_SENDING;
+               /* Remove from send_list. Necessary to ensure BUG_ON() below is not triggered. */
+               LIST_DEL_INIT(&qcs->el_send);
+       }
+
        if (qcs_is_completed(qcs)) {
                BUG_ON(LIST_INLIST(&qcs->el_send));
                TRACE_STATE("add stream in purg_list", QMUX_EV_QCS_RECV, qcs->qcc->conn, qcs);