From: Frédéric Lécaille Date: Wed, 8 Nov 2023 10:31:21 +0000 (+0100) Subject: BUG/MEDIUM: quic: Avoid some crashes upon TX packet allocation failures X-Git-Tag: v2.9-dev10~121 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=819690303de91804e009dea31d1c4c9116666396;p=thirdparty%2Fhaproxy.git BUG/MEDIUM: quic: Avoid some crashes upon TX packet allocation failures If a TX packet cannot be allocated (by qc_build_pkt()), as it can be coalesced to another one, this leads the TX buffer to have remaining not sent prepared data. Then haproxy crashes upon a BUG_ON() triggered by the next call to qc_txb_release(). This may happen only during handshakes. To fix this, qc_build_pkt() returns a new -3 error to dected such allocation failures followed which is for now on followed by a call to qc_purge_txbuf() to send the TX prepared data and purge the TX buffer. Must be backported as far as 2.6. --- diff --git a/src/quic_tx.c b/src/quic_tx.c index 0a0e4bc799..f6976bc0e3 100644 --- a/src/quic_tx.c +++ b/src/quic_tx.c @@ -495,6 +495,9 @@ static int qc_prep_app_pkts(struct quic_conn *qc, struct buffer *buf, pkt = qc_build_pkt(&pos, end, qel, &qel->tls_ctx, frms, qc, NULL, 0, QUIC_PACKET_TYPE_SHORT, must_ack, 0, probe, cc, &err); switch (err) { + case -3: + qc_purge_txbuf(qc, buf); + goto leave; case -2: // trace already emitted by function above goto leave; @@ -1127,6 +1130,9 @@ int qc_prep_hpkts(struct quic_conn *qc, struct buffer *buf, struct list *qels) qc, ver, dglen, pkt_type, must_ack, padding, probe, cc, &err); switch (err) { + case -3: + qc_purge_tx_buf(qc, buf); + goto leave; case -2: // trace already emitted by function above goto leave; @@ -2472,8 +2478,8 @@ static inline void quic_tx_packet_init(struct quic_tx_packet *pkt, int type) * the end of this buffer, with as packet type for QUIC connection * at encryption level with list of prebuilt frames. * - * Return -2 if the packet could not be allocated or encrypted for any reason, - * -1 if there was not enough room to build a packet. + * Return -3 if the packet could not be allocated, -2 if could not be encrypted for + * any reason, -1 if there was not enough room to build a packet. * XXX NOTE XXX * If you provide provide qc_build_pkt() with a big enough buffer to build a packet as big as * possible (to fill an MTU), the unique reason why this function may fail is the congestion @@ -2502,7 +2508,7 @@ static struct quic_tx_packet *qc_build_pkt(unsigned char **pos, pkt = pool_alloc(pool_head_quic_tx_packet); if (!pkt) { TRACE_DEVEL("Not enough memory for a new packet", QUIC_EV_CONN_TXPKT, qc); - *err = -2; + *err = -3; goto err; }