From 36d28bfca36e164d4d669c62069861f004dc05e3 Mon Sep 17 00:00:00 2001 From: Amaury Denoyelle Date: Tue, 2 Sep 2025 09:22:24 +0200 Subject: [PATCH] MEDIUM: quic: strengthen BUG_ON() for unpad Initial packet on client To avoid anti-amplification limit, it is required that Initial packet are padded to be at least 1.200 bytes long. On server side, this only applies to ack-eliciting packets. However, for client side, this is mandatory for every packets. This patch adjusts qc_txb_store() BUG_ON statement used to catch too small Initial packets. On QUIC client side, ack-eliciting flag is now ignored, thus every packets are checked. This is labelled as MEDIUM as this BUG_ON() is known to be easily triggered, as QUIC datagrams encoding function are complex. However, it's important that a QUIC endpoint respects it, else the peer will drop the invalid packet and could immediately close the connection. --- src/quic_tx.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/quic_tx.c b/src/quic_tx.c index ee354470d..4f003240f 100644 --- a/src/quic_tx.c +++ b/src/quic_tx.c @@ -159,13 +159,14 @@ struct buffer *qc_get_txb(struct quic_conn *qc) * Caller is responsible that there is enough space in the buffer. */ static void qc_txb_store(struct buffer *buf, uint16_t length, - struct quic_tx_packet *first_pkt) + struct quic_tx_packet *first_pkt, + const struct quic_conn *qc) { BUG_ON_HOT(b_contig_space(buf) < QUIC_DGRAM_HEADLEN); /* this must not happen */ /* If first packet is INITIAL, ensure datagram is sufficiently padded. */ BUG_ON(first_pkt->type == QUIC_PACKET_TYPE_INITIAL && - (first_pkt->flags & QUIC_FL_TX_PACKET_ACK_ELICITING) && + (qc_is_back(qc) || (first_pkt->flags & QUIC_FL_TX_PACKET_ACK_ELICITING)) && length < QUIC_INITIAL_PACKET_MINLEN); write_u16(b_tail(buf), length); @@ -743,7 +744,7 @@ static int qc_prep_pkts(struct quic_conn *qc, struct buffer *buf, */ if (first_pkt && (first_pkt->type != QUIC_PACKET_TYPE_INITIAL || wrlen >= QUIC_INITIAL_PACKET_MINLEN)) { - qc_txb_store(buf, wrlen, first_pkt); + qc_txb_store(buf, wrlen, first_pkt, qc); } TRACE_PROTO("could not prepare anymore packet", QUIC_EV_CONN_PHPKTS, qc, qel); break; @@ -825,7 +826,7 @@ static int qc_prep_pkts(struct quic_conn *qc, struct buffer *buf, } else { /* Finalize current datagram if not all frames sent. */ - qc_txb_store(buf, wrlen, first_pkt); + qc_txb_store(buf, wrlen, first_pkt, qc); first_pkt = NULL; wrlen = dglen = 0; padding = 0; @@ -844,7 +845,7 @@ static int qc_prep_pkts(struct quic_conn *qc, struct buffer *buf, out: if (first_pkt) - qc_txb_store(buf, wrlen, first_pkt); + qc_txb_store(buf, wrlen, first_pkt, qc); if (cc && total) { BUG_ON(buf != &qc->tx.cc_buf);