]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MINOR: quic: Possible stream truncations under heavy loss
authorFrédéric Lécaille <flecaille@haproxy.com>
Thu, 26 Jan 2023 14:07:39 +0000 (15:07 +0100)
committerWilly Tarreau <w@1wt.eu>
Fri, 3 Feb 2023 16:55:55 +0000 (17:55 +0100)
This may happen during retransmission of frames which can be splitted
(CRYPTO, or STREAM frames). One may have to split a frame to be
retransmitted due to the QUIC protocol properties (packet size limitation
and packet field encoding sizes). The remaining part of a frame which
cannot be retransmitted must be detached from the original frame it is
copied from. If not, when the really sent part will be acknowledged
the remaining part will be acknowledged too but not sent!

Must be backported to 2.7 and 2.6.

src/quic_conn.c

index 9d167cc8a0450ccc6c9d1fb0dd5e676f8356535e..8fa28ba2fafbe0a45141496b57ec542a563fa3ee 100644 (file)
@@ -6730,6 +6730,9 @@ static inline int qc_build_frms(struct list *outlist, struct list *inlist,
                                        /* This <cf> frame was duplicated */
                                        LIST_APPEND(&cf->origin->reflist, &new_cf->ref);
                                        new_cf->origin = cf->origin;
+                                       /* Detach the remaining CRYPTO frame from its original frame */
+                                       LIST_DEL_INIT(&cf->ref);
+                                       cf->origin = NULL;
                                }
                                LIST_APPEND(outlist, &new_cf->list);
                                /* Consume <dlen> bytes of the current frame. */
@@ -6842,6 +6845,9 @@ static inline int qc_build_frms(struct list *outlist, struct list *inlist,
                                        /* This <cf> frame was duplicated */
                                        LIST_APPEND(&cf->origin->reflist, &new_cf->ref);
                                        new_cf->origin = cf->origin;
+                                       /* Detach this STREAM frame from its origin */
+                                       LIST_DEL_INIT(&cf->ref);
+                                       cf->origin = NULL;
                                }
                                LIST_APPEND(outlist, &new_cf->list);
                                cf->type |= QUIC_STREAM_FRAME_TYPE_OFF_BIT;