From a45f90dd4e2bf65da2b04a78117100534e43c321 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20L=C3=A9caille?= Date: Fri, 4 Aug 2023 15:10:56 +0200 Subject: [PATCH] MINOR: quic: Amplification limit handling sanitization. Add a BUG_ON() to quic_peer_validated_addr() to check the amplification limit is respected when it return false(0), i.e. when the connection is not validated. Implement quic_may_send_bytes() which returns the number of bytes which may be sent when the connection has not already been validated and call this functions at several places when this is the case (after having called quic_peer_validated_addr()). Furthermore, this patch improves the code maintainability. Some patches to come will have to rename ->[rt]x.bytes quic_conn struct members. --- include/haproxy/quic_conn.h | 10 ++++++++++ src/quic_conn.c | 2 ++ src/quic_tx.c | 11 ++++++----- 3 files changed, 18 insertions(+), 5 deletions(-) diff --git a/include/haproxy/quic_conn.h b/include/haproxy/quic_conn.h index 040809062..0f4ab0bad 100644 --- a/include/haproxy/quic_conn.h +++ b/include/haproxy/quic_conn.h @@ -467,6 +467,16 @@ static inline size_t quic_path_prep_data(struct quic_path *path) return path->cwnd - path->prep_in_flight; } +/* Return the number of bytes which may be sent from connection when + * it has not already been validated. Note that this is the responsability + * of the caller to check that the case with quic_peer_validated_addr(). + * This latter BUG_ON() if 3 * qc->rx.bytes < qc->tx.prep_bytes. + */ +static inline size_t quic_may_send_bytes(struct quic_conn *qc) +{ + return 3 * qc->rx.bytes - qc->tx.prep_bytes; +} + /* CRYPTO data buffer handling functions. */ static inline unsigned char *c_buf_getpos(struct quic_enc_level *qel, uint64_t offset) { diff --git a/src/quic_conn.c b/src/quic_conn.c index 178a14804..5a4fcfaf3 100644 --- a/src/quic_conn.c +++ b/src/quic_conn.c @@ -149,6 +149,8 @@ int quic_peer_validated_addr(struct quic_conn *qc) qc->state >= QUIC_HS_ST_COMPLETE) return 1; + BUG_ON(qc->tx.prep_bytes > 3 * qc->rx.bytes); + return 0; } diff --git a/src/quic_tx.c b/src/quic_tx.c index 3db0ac341..4f479596e 100644 --- a/src/quic_tx.c +++ b/src/quic_tx.c @@ -233,7 +233,7 @@ static void qc_prep_fast_retrans(struct quic_conn *qc, * packet size is the packet number. And the maximum increase is 4 bytes. */ if (!quic_peer_validated_addr(qc) && qc_is_listener(qc) && - pkt->len + 4 > 3 * qc->rx.bytes - qc->tx.prep_bytes) { + pkt->len + 4 > quic_may_send_bytes(qc)) { qc->flags |= QUIC_FL_CONN_ANTI_AMPLIFICATION_REACHED; TRACE_PROTO("anti-amplification limit would be reached", QUIC_EV_CONN_SPPKTS, qc, pkt); goto leave; @@ -298,8 +298,9 @@ void qc_prep_hdshk_fast_retrans(struct quic_conn *qc, */ if (!quic_peer_validated_addr(qc) && qc_is_listener(qc)) { size_t dglen = pkt->len + 4; - size_t may_send = 3 * qc->rx.bytes - qc->tx.prep_bytes; + size_t may_send; + may_send = quic_may_send_bytes(qc); dglen += pkt->next ? pkt->next->len + 4 : 0; if (dglen > may_send) { qc->flags |= QUIC_FL_CONN_ANTI_AMPLIFICATION_REACHED; @@ -468,7 +469,7 @@ static int qc_prep_app_pkts(struct quic_conn *qc, struct buffer *buf, /* Leave room for the datagram header */ pos += dg_headlen; if (!quic_peer_validated_addr(qc) && qc_is_listener(qc)) { - end = pos + QUIC_MIN((uint64_t)qc->path->mtu, 3 * qc->rx.bytes - qc->tx.prep_bytes); + end = pos + QUIC_MIN((uint64_t)qc->path->mtu, quic_may_send_bytes(qc)); } else { end = pos + qc->path->mtu; @@ -1043,7 +1044,7 @@ int qc_prep_hpkts(struct quic_conn *qc, struct buffer *buf, struct list *qels) /* Leave room for the datagram header */ pos += dg_headlen; if (!quic_peer_validated_addr(qc) && qc_is_listener(qc)) { - end = pos + QUIC_MIN((uint64_t)qc->path->mtu, 3 * qc->rx.bytes - qc->tx.prep_bytes); + end = pos + QUIC_MIN((uint64_t)qc->path->mtu, quic_may_send_bytes(qc)); } else { end = pos + qc->path->mtu; @@ -1357,7 +1358,7 @@ int qc_need_sending(struct quic_conn *qc, struct quic_enc_level *qel) int qc_may_probe_ipktns(struct quic_conn *qc) { return quic_peer_validated_addr(qc) || - (int)(3 * qc->rx.bytes - qc->tx.prep_bytes) >= QUIC_INITIAL_PACKET_MINLEN; + quic_may_send_bytes(qc) >= QUIC_INITIAL_PACKET_MINLEN; } /*