From: Frédéric Lécaille Date: Tue, 7 Nov 2023 17:27:50 +0000 (+0100) Subject: BUG/MEDIUM: quic: Avoid trying to send ACK frames from an empty ack ranges tree X-Git-Tag: v2.9-dev10~123 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=c78cb49a3b432cabe54804b462a6a83e6dda1cfd;p=thirdparty%2Fhaproxy.git BUG/MEDIUM: quic: Avoid trying to send ACK frames from an empty ack ranges tree This may happen upon ack ranges allocation failures (from quic_update_ack_ranges_list(). This can lead to empty trees of ack ranges to be used to build ACK frames which is not good at all. Furthermore this is detected by a BUG_ON() (in qc_do_build_pkt()). To avoid this, simply update the acknowledgemen state of the connection only if quic_update_ack_ranges_list() succeeds, as it fails only in case of memory allocation failures. Must be backported as far as 2.6. --- diff --git a/src/quic_rx.c b/src/quic_rx.c index e2f3f89563..37ab52176b 100644 --- a/src/quic_rx.c +++ b/src/quic_rx.c @@ -1381,23 +1381,27 @@ int qc_treat_rx_pkts(struct quic_conn *qc) else { struct quic_arng ar = { .first = pkt->pn, .last = pkt->pn }; - if (pkt->flags & QUIC_FL_RX_PACKET_ACK_ELICITING) { - int arm_ack_timer = - qc->state >= QUIC_HS_ST_COMPLETE && - qel->pktns == qc->apktns; - - qel->pktns->flags |= QUIC_FL_PKTNS_ACK_REQUIRED; - qel->pktns->rx.nb_aepkts_since_last_ack++; - qc_idle_timer_rearm(qc, 1, arm_ack_timer); - } - if (pkt->pn > largest_pn) { - largest_pn = pkt->pn; - largest_pn_time_received = pkt->time_received; - } /* Update the list of ranges to acknowledge. */ - if (!quic_update_ack_ranges_list(qc, &qel->pktns->rx.arngs, &ar)) + if (quic_update_ack_ranges_list(qc, &qel->pktns->rx.arngs, &ar)) { + if (pkt->flags & QUIC_FL_RX_PACKET_ACK_ELICITING) { + int arm_ack_timer = + qc->state >= QUIC_HS_ST_COMPLETE && + qel->pktns == qc->apktns; + + qel->pktns->flags |= QUIC_FL_PKTNS_ACK_REQUIRED; + qel->pktns->rx.nb_aepkts_since_last_ack++; + qc_idle_timer_rearm(qc, 1, arm_ack_timer); + } + + if (pkt->pn > largest_pn) { + largest_pn = pkt->pn; + largest_pn_time_received = pkt->time_received; + } + } + else { TRACE_ERROR("Could not update ack range list", QUIC_EV_CONN_RXPKT, qc); + } } } node = eb64_next(node);