From: Amaury Denoyelle Date: Mon, 6 Mar 2023 08:10:53 +0000 (+0100) Subject: BUG/MEDIUM: quic: do not crash when handling STREAM on released MUX X-Git-Tag: v2.8-dev5~32 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=315a4f6ae54da17fd28f7a14373b05bab0b5aa08;p=thirdparty%2Fhaproxy.git BUG/MEDIUM: quic: do not crash when handling STREAM on released MUX The MUX instance is released before its quic-conn counterpart. On termination, a H3 GOAWAY is emitted to prevent the client to open new streams for this connection. The quic-conn instance will stay alive until all opened streams data are acknowledged. If the client tries to open a new stream during this interval despite the GOAWAY, quic-conn is responsible to request its immediate closure with a STOP_SENDING + RESET_STREAM. This behavior was already implemented but the received packet with the new STREAM was never acknowledged. This was fixed with the following commit : commit 156a89aef8c63910502b266251dc34f648a99fae BUG/MINOR: quic: acknowledge STREAM frame even if MUX is released However, this patch introduces a regression as it did not skip the call to qc_handle_strm_frm() despite the MUX instance being released. This can cause a segfault when using qcc_get_qcs() on a released MUX instance. To fix this, add a missing break statement which will skip qc_handle_strm_frm() when the MUX instance is not initialized. This commit was reproduced using a short timeout client and sending several requests with delay between them by using a modified aioquic. It produces a crash with the following backtrace : #0 0x000055555594d261 in __eb64_lookup (x=4, root=0x7ffff4091f60) at include/import/eb64tree.h:132 #1 eb64_lookup (root=0x7ffff4091f60, x=4) at src/eb64tree.c:37 #2 0x000055555563fc66 in qcc_get_qcs (qcc=0x7ffff4091dc0, id=4, receive_only=1, send_only=0, out=0x7ffff780ca70) at src/mux_quic.c:668 #3 0x0000555555641e1a in qcc_recv (qcc=0x7ffff4091dc0, id=4, len=40, offset=0, fin=1 '\001', data=0x7ffff40c4fef "\001&") at src/mux_quic.c:974 #4 0x0000555555619d28 in qc_handle_strm_frm (pkt=0x7ffff4088e60, strm_frm=0x7ffff780cf50, qc=0x7ffff7cef000, fin=1 '\001') at src/quic_conn.c:2515 #5 0x000055555561d677 in qc_parse_pkt_frms (qc=0x7ffff7cef000, pkt=0x7ffff4088e60, qel=0x7ffff7cef6c0) at src/quic_conn.c:3050 #6 0x00005555556230aa in qc_treat_rx_pkts (qc=0x7ffff7cef000, cur_el=0x7ffff7cef6c0, next_el=0x0) at src/quic_conn.c:4214 #7 0x0000555555625fee in quic_conn_app_io_cb (t=0x7ffff40c1fa0, context=0x7ffff7cef000, state=32848) at src/quic_conn.c:4640 #8 0x00005555558a676d in run_tasks_from_lists (budgets=0x7ffff780d470) at src/task.c:596 #9 0x00005555558a725b in process_runnable_tasks () at src/task.c:876 #10 0x00005555558522ba in run_poll_loop () at src/haproxy.c:2945 #11 0x00005555558529ac in run_thread_poll_loop (data=0x555555d14440 ) at src/haproxy.c:3141 #12 0x00007ffff789ebb5 in ?? () from /usr/lib/libc.so.6 #13 0x00007ffff7920d90 in ?? () from /usr/lib/libc.so.6 This should fix github issue #2067. This must be backported up to 2.6. --- diff --git a/src/quic_conn.c b/src/quic_conn.c index 60af8b8c18..d8ae0385c6 100644 --- a/src/quic_conn.c +++ b/src/quic_conn.c @@ -3029,7 +3029,6 @@ static int qc_parse_pkt_frms(struct quic_conn *qc, struct quic_rx_packet *pkt, if (qc->mux_state != QC_MUX_READY) { if ((stream->id >> QCS_ID_TYPE_SHIFT) < nb_streams) { TRACE_DATA("Already closed stream", QUIC_EV_CONN_PRSHPKT, qc); - break; } else { TRACE_DEVEL("No mux for new stream", QUIC_EV_CONN_PRSHPKT, qc); @@ -3045,6 +3044,8 @@ static int qc_parse_pkt_frms(struct quic_conn *qc, struct quic_rx_packet *pkt, goto leave; } } + + break; } if (!qc_handle_strm_frm(pkt, stream, qc, fin)) {