]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MINOR: quic: Dropped retransmitted STREAM frames
authorFrédéric Lécaille <flecaille@haproxy.com>
Mon, 2 May 2022 16:52:58 +0000 (18:52 +0200)
committerAmaury Denoyelle <adenoyelle@haproxy.com>
Tue, 3 May 2022 08:13:40 +0000 (10:13 +0200)
It is possible that we continue to receive retransmitted STREAM frames after
the mux have been released. We rely on the ->rx.streams[].nb_streams counter
to check the stream was closed. If not, at this time we drop the packet.

src/xprt_quic.c

index a83fb0c1c903f4dbd7381869e04e0c63df4b8c20..524c42d2e1d40ae4005e02cc86228f8e9e80c0cb 100644 (file)
@@ -2689,6 +2689,7 @@ static int qc_parse_pkt_frms(struct quic_rx_packet *pkt, struct ssl_sock_ctx *ct
                case QUIC_FT_STREAM_8 ... QUIC_FT_STREAM_F:
                {
                        struct quic_stream *stream = &frm.stream;
+                       unsigned nb_streams = qc->rx.strms[qcs_id_type(stream->id)].nb_streams;
 
                        if (qc_is_listener(ctx->qc)) {
                                if (stream->id & QUIC_STREAM_FRAME_ID_INITIATOR_BIT)
@@ -2696,12 +2697,17 @@ static int qc_parse_pkt_frms(struct quic_rx_packet *pkt, struct ssl_sock_ctx *ct
                        } else if (!(stream->id & QUIC_STREAM_FRAME_ID_INITIATOR_BIT))
                                goto err;
 
-                       /* The upper layer may not be allocated.
-                        *
-                        * TODO emit a CONNECTION_CLOSE if mux already freed.
-                        */
-                       if (qc->mux_state != QC_MUX_READY)
-                               goto err;
+                       /* The upper layer may not be allocated. */
+                       if (qc->mux_state != QC_MUX_READY) {
+                               if ((stream->id >> QCS_ID_TYPE_SHIFT) < nb_streams) {
+                                       TRACE_PROTO("Already closed stream", QUIC_EV_CONN_PRSHPKT, qc);
+                                       break;
+                               }
+                               else {
+                                       TRACE_PROTO("Stream not found", QUIC_EV_CONN_PRSHPKT, qc);
+                                       goto err;
+                               }
+                       }
 
                        if (!qc_handle_strm_frm(pkt, stream, qc))
                                goto err;