From: Amaury Denoyelle Date: Wed, 5 Oct 2022 15:56:08 +0000 (+0200) Subject: MEDIUM: quic: requeue datagrams received on wrong socket X-Git-Tag: v2.8-dev1~185 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=b2bd83972b7f61f674871b9a9722a6192a841322;p=thirdparty%2Fhaproxy.git MEDIUM: quic: requeue datagrams received on wrong socket There is a small race condition when QUIC connection socket is instantiated between the bind() and connect() system calls. This means that the first datagram read on the sockets may belong to another connection. To detect this rare case, we compare the DCID for each QUIC datagram read on the QUIC socket. If it does not match the connection CID, the datagram is requeue using quic_receiver_buf to be able to handle it on the correct thread. This change is part of quic-conn owned socket implementation. It may be backported to 2.7 after a period of observation. --- diff --git a/src/quic_sock.c b/src/quic_sock.c index 5b10d8a8ad..284c9614d4 100644 --- a/src/quic_sock.c +++ b/src/quic_sock.c @@ -628,8 +628,37 @@ int qc_rcv_buf(struct quic_conn *qc) * * TODO count redispatch datagrams. */ - TRACE_STATE("wrong datagram on quic-conn socket, prepare to requeue it", QUIC_EV_CONN_RCV, qc); - ABORT_NOW(); + struct quic_receiver_buf *rxbuf; + struct quic_dgram *tmp_dgram; + unsigned char *rxbuf_tail; + + TRACE_STATE("datagram for other connection on quic-conn socket, requeue it", QUIC_EV_CONN_RCV, qc); + + rxbuf = MT_LIST_POP(&l->rx.rxbuf_list, typeof(rxbuf), rxbuf_el); + + tmp_dgram = quic_rxbuf_purge_dgrams(rxbuf); + pool_free(pool_head_quic_dgram, tmp_dgram); + + if (b_contig_space(&rxbuf->buf) < new_dgram->len) { + /* TODO count lost datagrams */ + MT_LIST_APPEND(&l->rx.rxbuf_list, &rxbuf->rxbuf_el); + continue; + } + + rxbuf_tail = (unsigned char *)b_tail(&rxbuf->buf); + __b_putblk(&rxbuf->buf, (char *)dgram_buf, new_dgram->len); + if (!quic_lstnr_dgram_dispatch(rxbuf_tail, ret, l, &qc->peer_addr, &daddr, + new_dgram, &rxbuf->dgram_list)) { + /* TODO count lost datagrams. */ + b_sub(&buf, ret); + } + else { + /* datagram must not be freed as it was requeued. */ + new_dgram = NULL; + } + + MT_LIST_APPEND(&l->rx.rxbuf_list, &rxbuf->rxbuf_el); + continue; } quic_dgram_parse(new_dgram, qc, qc->li);