BUG/MINOR: mux-quic: remove full demux flag on ncbuf release
authorAmaury Denoyelle <adenoyelle@haproxy.com>
Thu, 21 Sep 2023 15:06:16 +0000 (17:06 +0200)
committerAmaury Denoyelle <adenoyelle@haproxy.com>
Thu, 28 Sep 2023 09:44:53 +0000 (11:44 +0200)
commit7cf9cf705ed0284ac1160adb66be19c1d57986a9
tree8ece0af5617f27f3fd7d099ad653d9768b74c3e9
parentf8b81f6eb7ff7691ef7ade3a2afb77dec8ba8d34
BUG/MINOR: mux-quic: remove full demux flag on ncbuf release

When rcv_buf stream callback is invoked, mux tasklet is woken up if
demux was previously blocked due to lack of buffer space. A BUG_ON() is
present to ensure there is data in qcs Rx buffer. If this is not the
case, wakeup is unneeded :

  BUG_ON(!ncb_data(&qcs->rx.ncbuf, 0));

This BUG_ON() may be triggered if RESET_STREAM is received after demux
has been blocked. On reset, Rx buffer is purged according to RFC 9000
which allows to discard any data not yet consumed. This will trigger the
BUG_ON() assertion if rcv_buf stream callback is invoked after this.

To prevent BUG_ON() crash, just clear demux block flag each time Rx
buffer is purged. This covers accordingly RESET_STREAM reception.

This should be backported up to 2.7.

This may fix github issue #2293.

This bug relies on several precondition so its occurence is rare. This
was reproduced by using a custom client which post big enough data to
fill the buffer. It then emits a RESET_STREAM in place of a proper FIN.
Moreover, mux code has been edited to artificially stalled stream read
to force demux blocking.

h3_data_to_htx:
-       return htx_sent;
+       return 1;

qcc_recv_reset_stream:
        qcs_free_ncbuf(qcs, &qcs->rx.ncbuf);
+       qcs_notify_recv(qcs);

qmux_strm_rcv_buf:
        char fin = 0;
+       static int i = 0;
+       if (++i < 2)
+               return 0;
        TRACE_ENTER(QMUX_EV_STRM_RECV, qcc->conn, qcs);
src/mux_quic.c