]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MINOR: quic: Wrong Application encryption level selection when probing
authorFrédéric Lécaille <flecaille@haproxy.com>
Thu, 13 Apr 2023 16:30:16 +0000 (18:30 +0200)
committerFrédéric Lécaille <flecaille@haproxy.com>
Thu, 13 Apr 2023 17:20:09 +0000 (19:20 +0200)
This bug arrived with this commit:

    MEDIUM: quic: Ack delay implementation

After having probed the Handshake packet number space, one must not select the
Application encryption level to continue trying building packets as this is done
when the connection is not probing. Indeed, if the ACK timer has been triggered
in the meantime, the packet builder will try to build a packet at the Application
encryption level to acknowledge the received packet. But there is very often
no 01RTT packet to acknowledge when the connection is probing before the
handshake is completed. This triggers a BUG_ON() in qc_do_build_pkt() which
checks that the tree of ACK ranges to be used is not empty.

Thank you to @Tristan971 for having reported this issue in GH #2109.

Must be backported to 2.6 and 2.7.

src/quic_conn.c

index 95ba744f64de569c5e235e5f01cb518a5ca49b41..5c1d64e694f9d0ddb56c23c500699e1ad177306c 100644 (file)
@@ -3676,9 +3676,19 @@ static int qc_prep_pkts(struct quic_conn *qc, struct buffer *buf,
                 */
                if ((tel == QUIC_TLS_ENC_LEVEL_INITIAL || tel == QUIC_TLS_ENC_LEVEL_HANDSHAKE) &&
                    next_tel != QUIC_TLS_ENC_LEVEL_NONE && (LIST_ISEMPTY(frms))) {
-                       /* If QUIC_TLS_ENC_LEVEL_HANDSHAKE was already reached let's try QUIC_TLS_ENC_LEVEL_APP */
-                       if (tel == QUIC_TLS_ENC_LEVEL_HANDSHAKE && next_tel == tel)
+                       /* If QUIC_TLS_ENC_LEVEL_HANDSHAKE was already reached let's try
+                        * QUIC_TLS_ENC_LEVEL_APP except if the connection was probing.
+                        */
+                       if (tel == QUIC_TLS_ENC_LEVEL_HANDSHAKE && next_tel == tel) {
+                               if ((qc->pktns->flags & QUIC_FL_PKTNS_PROBE_NEEDED)) {
+                                       TRACE_PROTO("skip APP enc. level", QUIC_EV_CONN_PHPKTS, qc);
+                                       qc_txb_store(buf, dglen, first_pkt);
+                                       goto out;
+                               }
+
                                next_tel = QUIC_TLS_ENC_LEVEL_APP;
+                       }
+
                        tel = next_tel;
                        if (tel == QUIC_TLS_ENC_LEVEL_APP)
                                frms = &qc->els[tel].pktns->tx.frms;