]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MINOR: mux-quic: fix crash on aborting uni remote stream
authorAmaury Denoyelle <adenoyelle@haproxy.com>
Tue, 5 Mar 2024 14:14:08 +0000 (15:14 +0100)
committerAmaury Denoyelle <adenoyelle@haproxy.com>
Wed, 6 Mar 2024 09:41:01 +0000 (10:41 +0100)
A remote unidirectional stream can be aborted prematurely if application
layers cannot identify its type. In this case, a STOP_SENDING frame is
emitted.

Since QUIC MUX refactoring, a crash would occur in this scenario due to
2 specific characteristics of remote uni streams :
* qcs.tx.fctl was not initialized completely. This cause a crash due to
  BUG_ON() statement inside qcs_destroy().
* qcs.stream is never allocated. This caused qcs_prep_bytes() to crash
  inside qcc_io_send().

This bug is considered minor as it happens only on very specific QUIC
clients. It was detected when using s2n-quic over interop.

This does not need to be backported.

src/mux_quic.c

index adcda3595c750627061c20117b6523da56767a82..9357145ef33b338ba4dde85d5f9f3c804c14c84f 100644 (file)
@@ -127,7 +127,7 @@ static struct qcs *qcs_new(struct qcc *qcc, uint64_t id, enum qcs_type type)
                qfctl_init(&qcs->tx.fc, qcc->rfctl.msd_uni_l);
        }
        else {
-               qcs->tx.fc.off_real = 0;
+               qfctl_init(&qcs->tx.fc, 0);
        }
 
        qcs->rx.ncbuf = NCBUF_NULL;
@@ -2115,7 +2115,7 @@ static int qcc_io_send(struct qcc *qcc)
 
                /* Stream must not be present in send_list if it has nothing to send. */
                BUG_ON(!(qcs->flags & (QC_SF_FIN_STREAM|QC_SF_TO_STOP_SENDING|QC_SF_TO_RESET)) &&
-                      !qcs_prep_bytes(qcs));
+                      (!qcs->stream || !qcs_prep_bytes(qcs)));
 
                /* Each STOP_SENDING/RESET_STREAM frame is sent individually to
                 * guarantee its emission.
@@ -2130,7 +2130,7 @@ static int qcc_io_send(struct qcc *qcc)
                         * to send.
                         */
                        if (!(qcs->flags & (QC_SF_FIN_STREAM|QC_SF_TO_RESET)) &&
-                           !qcs_prep_bytes(qcs)) {
+                           (!qcs->stream || !qcs_prep_bytes(qcs))) {
                                LIST_DEL_INIT(&qcs->el_send);
                                continue;
                        }