From b578283d0238a70ada5bb1a7a5878e7270a311c9 Mon Sep 17 00:00:00 2001 From: Frederic Lecaille Date: Mon, 1 Sep 2025 14:35:14 +0200 Subject: [PATCH] BUG/MINOR: quic: ignore AGAIN ncbuf err when parsing CRYPTO frames This fix follows this previous one: BUG/MINOR: quic: reorder fragmented RX CRYPTO frames by their offsets which is not sufficient when a client fragments and mixes its CRYPTO frames AND leaveswith holes by packets. ngtcp2 (and perhaps chrome) splits theire CRYPTO frames but without hole by packet. In such a case, the CRYPTO parsing leads to QUIC_RX_RET_FRM_AGAIN errors which cannot be fixed when the peer resends its packets. Indeed, even if the peer resends its frames in a different order, this does not help because since the previous commit, the CRYPTO frames are ordered on haproxy side. This issue was detected thanks to the interopt tests with quic-go as client. This client fragments its CRYPTO frames, mixes them, and generate holes, and most of the times with the retry test. To fix this, when a QUIC_RX_RET_FRM_AGAIN error is encountered, the CRYPTO frames parsing is not stop. This leaves chances to the next CRYPTO frames to be parsed. Must be backported as far as 2.6 as the commit mentioned above. (cherry picked from commit fba80c7fe84707afe134a5b240a2842a0a51f78f) Signed-off-by: Christopher Faulet (cherry picked from commit 02d7f2b30df2c6dd4de371c31eab423e9e7bce1f) Signed-off-by: Christopher Faulet (cherry picked from commit 47a60d8c8e446456cc3406ac5540fbc4180d9ff5) Signed-off-by: Christopher Faulet --- src/quic_rx.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/quic_rx.c b/src/quic_rx.c index 96c3be0..e3869c6 100644 --- a/src/quic_rx.c +++ b/src/quic_rx.c @@ -838,7 +838,7 @@ static int qc_parse_pkt_frms(struct quic_conn *qc, struct quic_rx_packet *pkt, struct quic_frame *frm = NULL; const unsigned char *pos, *end; enum quic_rx_ret_frm ret; - int fast_retrans = 0; + int fast_retrans = 0, cf_err = 0; TRACE_ENTER(QUIC_EV_CONN_PRSHPKT, qc); /* Skip the AAD */ @@ -1101,9 +1101,8 @@ static int qc_parse_pkt_frms(struct quic_conn *qc, struct quic_rx_packet *pkt, case QUIC_RX_RET_FRM_AGAIN: TRACE_STATE("AGAIN encountered", QUIC_EV_CONN_PRSHPKT, qc); - /* avoid freeing without eb_delete() */ - frm = NULL; - goto err; + cf_err = 1; + break; case QUIC_RX_RET_FRM_DONE: TRACE_PROTO("frame handled", QUIC_EV_CONN_PRSAFRM, qc, frm); @@ -1121,6 +1120,9 @@ static int qc_parse_pkt_frms(struct quic_conn *qc, struct quic_rx_packet *pkt, qc_frm_free(qc, &frm); } + if (cf_err) + goto err; + /* Error should be returned if some frames cannot be parsed. */ BUG_ON(!eb_is_empty(&cf_frms_tree)); -- 1.7.10.4