]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MINOR: quic: Missing Initial packet length check
authorFrédéric Lécaille <flecaille@haproxy.com>
Wed, 27 Apr 2022 09:42:08 +0000 (11:42 +0200)
committerAmaury Denoyelle <adenoyelle@haproxy.com>
Thu, 28 Apr 2022 14:22:40 +0000 (16:22 +0200)
Any client Initial packet carried in a datagram smaller than QUIC_INITIAL_PACKET_MINLEN(200)
bytes must be discarded. This does not mean we must discard the entire datagram.
So we must at least try to parse the packet length before dropping the packet
and return its length from qc_lstnr_pkt_rcv().

src/xprt_quic.c

index 0065e7fcf0658936a5e878660393b39f522f4d58..2ffad64e0a23efc337f4d0deee004fd8672788c1 100644 (file)
@@ -5025,12 +5025,19 @@ static ssize_t qc_lstnr_pkt_rcv(unsigned char *buf, const unsigned char *end,
        qc_parse_hd_form(pkt, *buf++, &long_header);
        if (long_header) {
                uint64_t len;
+               int drop_no_con = 0;
 
                if (!quic_packet_read_long_header(&buf, end, pkt)) {
                        TRACE_PROTO("Packet dropped", QUIC_EV_CONN_LPKT);
                        goto err;
                }
 
+               if (pkt->type == QUIC_PACKET_TYPE_INITIAL &&
+                   dgram->len < QUIC_INITIAL_PACKET_MINLEN) {
+                       TRACE_PROTO("Too short datagram with an Initial packet", QUIC_EV_CONN_LPKT, qc);
+                       drop_no_con = 1;
+               }
+
                /* When multiple QUIC packets are coalesced on the same UDP datagram,
                 * they must have the same DCID.
                 */
@@ -5108,6 +5115,8 @@ static ssize_t qc_lstnr_pkt_rcv(unsigned char *buf, const unsigned char *end,
 
                payload = buf;
                pkt->len = len + payload - beg;
+               if (drop_no_con)
+                       goto drop_no_con;
 
                qc = retrieve_qc_conn_from_cid(pkt, l, &dgram->saddr);
                if (!qc) {
@@ -5322,6 +5331,7 @@ static ssize_t qc_lstnr_pkt_rcv(unsigned char *buf, const unsigned char *end,
        if (conn_ctx)
                tasklet_wakeup(conn_ctx->wait_event.tasklet);
 
+ drop_no_con:
        TRACE_LEAVE(QUIC_EV_CONN_LPKT, qc ? qc : NULL, pkt);
 
        return pkt->len;