BUG/MINOR: h3: fix BUG_ON() crash on control stream alloc failure
authorAmaury Denoyelle <adenoyelle@haproxy.com>
Thu, 20 Jun 2024 15:51:35 +0000 (17:51 +0200)
committerChristopher Faulet <cfaulet@haproxy.com>
Wed, 26 Jun 2024 13:16:24 +0000 (15:16 +0200)
BUG_ON() from qcc_set_error() is triggered on HTTP/3 control stream
allocation failure. This is caused because both h3_finalize() and
qcc_init_stream_local() call qcc_set_error() which is forbidden to
prevent error code erasure.

Fix this by removing qcc_set_error() invocation from h3_finalize() on
allocation failure. Note that this function is still responsible to use
it on SETTING frame emission failure.

This was detected using -dMfail.

This must be backported up to 3.0.

(cherry picked from commit 5718c67c19766c87bb68b7624e1873a887fbbaf1)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>

src/h3.c
src/mux_quic.c

index 3c9463d..2aa4fa7 100644 (file)
--- a/src/h3.c
+++ b/src/h3.c
@@ -2378,20 +2378,23 @@ static int h3_finalize(void *ctx)
 
        qcs = qcc_init_stream_local(qcc, 0);
        if (!qcs) {
+               /* Error must be set by qcc_init_stream_local(). */
+               BUG_ON(!(qcc->flags & QC_CF_ERRL));
                TRACE_ERROR("cannot init control stream", H3_EV_H3C_NEW, qcc->conn);
                goto err;
        }
 
        h3c->ctrl_strm = qcs;
 
-       if (h3_control_send(qcs, h3c) < 0)
+       if (h3_control_send(qcs, h3c) < 0) {
+               qcc_set_error(qcc, H3_ERR_INTERNAL_ERROR, 1);
                goto err;
+       }
 
        TRACE_LEAVE(H3_EV_H3C_NEW, qcc->conn);
        return 0;
 
  err:
-       qcc_set_error(qcc, H3_ERR_INTERNAL_ERROR, 1);
        TRACE_DEVEL("leaving on error", H3_EV_H3C_NEW, qcc->conn);
        return 1;
 }
index 9c8f55e..15a2ed0 100644 (file)
@@ -617,8 +617,8 @@ struct qcs *qcc_init_stream_local(struct qcc *qcc, int bidi)
 
        qcs = qcs_new(qcc, *next, type);
        if (!qcs) {
-               TRACE_LEAVE(QMUX_EV_QCS_NEW, qcc->conn);
                qcc_set_error(qcc, QC_ERR_INTERNAL_ERROR, 0);
+               TRACE_DEVEL("leaving on error", QMUX_EV_QCS_NEW, qcc->conn);
                return NULL;
        }