]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MINOR: mux-quic: do not free frame already released by quic-conn
authorAmaury Denoyelle <adenoyelle@haproxy.com>
Tue, 9 May 2023 12:10:55 +0000 (14:10 +0200)
committerAmaury Denoyelle <adenoyelle@haproxy.com>
Thu, 11 May 2023 12:04:51 +0000 (14:04 +0200)
MUX uses qc_send_mux() function to send frames list over a QUIC
connection. On network congestion, the lower layer will reject some
frames and it is the MUX responsibility to free them. There is another
category of error which are when the sendto() fails. In this case, the
lower layer will free the packet and its attached frames and the MUX
should not touch them.

This model was violated by MUX layer for RESET_STREAM and STOP_SENDING
emission. In this case, frames were freed every time by the MUX on
error. This causes a double free error which lead to a crash.

Fix this by always ensuring if frames were rejected by the lower layer
before freeing them on the MUX. This is done simply by checking if frame
list is not empty, as RESET_STREAM and STOP_SENDING are sent
individually.

This bug was never reproduced in production. Thus, it is labelled as
MINOR.

This must be backported up to 2.7.

src/mux_quic.c

index 785f7b4b0b7a606eda7f03a084fff1a65934b434..259c7433f91278d1a78c923b9c5965d3fbcbc211 100644 (file)
@@ -1715,7 +1715,8 @@ static int qcs_send_reset(struct qcs *qcs)
 
        LIST_APPEND(&frms, &frm->list);
        if (qc_send_frames(qcs->qcc, &frms)) {
-               qc_frm_free(&frm);
+               if (!LIST_ISEMPTY(&frms))
+                       qc_frm_free(&frm);
                TRACE_DEVEL("cannot send RESET_STREAM", QMUX_EV_QCS_SEND, qcs->qcc->conn, qcs);
                return 1;
        }
@@ -1770,7 +1771,8 @@ static int qcs_send_stop_sending(struct qcs *qcs)
 
        LIST_APPEND(&frms, &frm->list);
        if (qc_send_frames(qcs->qcc, &frms)) {
-               qc_frm_free(&frm);
+               if (!LIST_ISEMPTY(&frms))
+                       qc_frm_free(&frm);
                TRACE_DEVEL("cannot send STOP_SENDING", QMUX_EV_QCS_SEND, qcs->qcc->conn, qcs);
                return 1;
        }