]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
BUG/MINOR: xprt_qstrm: prevent crash if conn release on MUX wake
authorAmaury Denoyelle <adenoyelle@haproxy.com>
Thu, 23 Apr 2026 15:32:44 +0000 (17:32 +0200)
committerAmaury Denoyelle <adenoyelle@haproxy.com>
Fri, 24 Apr 2026 07:33:04 +0000 (09:33 +0200)
When QMux XPRT has successfully been able to process to transport
parameters exchange, the MUX is initialized and immediately woken up to
start transfers. However, if the connection is in an unusable state, the
latter operation will instead release the connection and all of its
network stack.

A crash would occur in case of release when finalizing the XPRT tasklet
completion. To fix this, first free every XPRT resources. MUX wake is
now conducted in a safe way as the last operation before the tasklet is
completely released.

No need to backport.

src/xprt_qstrm.c

index 6583252250307a0883287ee4d88efa9d630321c0..b219c4970cdc5d12df3d44fbdff3fc857c9d5727 100644 (file)
@@ -182,6 +182,7 @@ struct task *xprt_qstrm_io_cb(struct task *t, void *context, unsigned int state)
 {
        struct xprt_qstrm_ctx *ctx = context;
        struct connection *conn = ctx->conn;
+       int ret;
 
        if (conn->flags & CO_FL_QSTRM_SEND) {
                if (!conn_send_qstrm(conn, ctx, CO_FL_QSTRM_SEND)) {
@@ -212,8 +213,7 @@ struct task *xprt_qstrm_io_cb(struct task *t, void *context, unsigned int state)
                /* MUX will access members from xprt_ctx on init, so create
                 * operation should be called before any members are resetted.
                 */
-               if (conn_create_mux(conn, NULL) == 0)
-                       conn->mux->wake(conn);
+               ret = conn_create_mux(conn, NULL);
 
                conn->xprt_ctx = ctx->ctx_lower;
                conn->xprt = ctx->ops_lower;
@@ -224,6 +224,14 @@ struct task *xprt_qstrm_io_cb(struct task *t, void *context, unsigned int state)
                tasklet_free(ctx->wait_event.tasklet);
                pool_free(xprt_qstrm_ctx_pool, ctx);
                t = NULL;
+
+               if (ret == 0) {
+                       /* Wake up MUX layer. This operation may also free the
+                        * connection and its XPRT, so it is safest to run it
+                        * after the current xprt layer release.
+                        */
+                       conn->mux->wake(conn);
+               }
        }
 
        return t;