]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
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)
committerAmaury Denoyelle <adenoyelle@haproxy.com>
Mon, 24 Jun 2024 12:40:38 +0000 (14:40 +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.

src/h3.c
src/mux_quic.c

index 3c9463d9222dbae21a58f082981a69e4fc70bb70..2aa4fa78e3a18799944a19db1a8843d06a11f16a 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 2b408cecf6020ca59d704ad65adfe34232a3ed8f..8e7f1c326c3e2009001aa1b5381561de97d951f9 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;
        }