]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: quic: Amplification limit handling sanitization.
authorFrédéric Lécaille <flecaille@haproxy.com>
Fri, 4 Aug 2023 13:10:56 +0000 (15:10 +0200)
committerFrédéric Lécaille <flecaille@haproxy.com>
Mon, 7 Aug 2023 16:57:45 +0000 (18:57 +0200)
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
src/quic_conn.c
src/quic_tx.c

index 0408090622c4323aa9c8fdca80c17cd83f8a3f4f..0f4ab0bad3b31739f006bdf50913fc7956bca322 100644 (file)
@@ -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 <qc> 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)
 {
index 178a1480442ada5fcb9d91c1214532a3e19ef102..5a4fcfaf3189726dd47d3b1b42b34c1fad843bed 100644 (file)
@@ -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;
 }
 
index 3db0ac341189654303e33e1815e3ec8cce914907..4f479596e3e27f3ec8743b995e5cfc6104b53215 100644 (file)
@@ -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;
 }
 
 /*