From 3ef1ee477d3fef54633465b603206dd00bfefeba Mon Sep 17 00:00:00 2001 From: Amaury Denoyelle Date: Wed, 7 Aug 2024 18:01:51 +0200 Subject: [PATCH] BUG/MINOR: quic: prevent freeze after early QCS closure A connection freeze may occur if a QCS is released before transmitting any data. This can happen when an error is detected early by the stream, for example during HTTP response headers encoding, forcing the whole connection closure. In this case, a connection error is registered by the QUIC MUX to the lower layer. MUX is then release and xprt layer is notified to prepare CONNECTION_CLOSE emission. However, this is prevented because quic_conn streams tree is not empty as it contains the qc_stream_desc previously attached to the failed QCS instance. The connection will freeze until QUIC idle timeout. This situation is caused by an omission during qc_stream_desc release operation. In the described situation, qc_stream_desc current buffer is empty and can thus by removed, which is the purpose of this patch. This unblocks this previously failed situation, with qc_stream_desc removal from quic_conn tree. This issue can be reproduced by modifying H3/QPACK code to return an early error during HEADERS response processing. This must be backported up to 2.6, after a period of observation. --- src/quic_stream.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/quic_stream.c b/src/quic_stream.c index 6a470488e..1d7a3c4de 100644 --- a/src/quic_stream.c +++ b/src/quic_stream.c @@ -120,12 +120,11 @@ void qc_stream_desc_release(struct qc_stream_desc *stream, BUG_ON(final_size > tail_offset); /* Remove unsent data from current buffer. */ - if (final_size < tail_offset) { + if (final_size < tail_offset) b_sub(buf, tail_offset - final_size); - /* Remove buffer if all ACK already received. */ - if (!b_data(buf)) - qc_stream_buf_free(stream, &stream_buf); - } + + if (!b_data(buf)) + qc_stream_buf_free(stream, &stream_buf); /* A released stream does not use . */ stream->buf = NULL;