From: Amaury Denoyelle Date: Thu, 23 Apr 2026 15:32:44 +0000 (+0200) Subject: BUG/MINOR: xprt_qstrm: prevent crash if conn release on MUX wake X-Git-Url: http://git.ipfire.org/gitweb/?a=commitdiff_plain;h=c08dcd3519f75fd65a310cc55f97a3fc1b9c76c9;p=thirdparty%2Fhaproxy.git BUG/MINOR: xprt_qstrm: prevent crash if conn release on MUX wake 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. --- diff --git a/src/xprt_qstrm.c b/src/xprt_qstrm.c index 658325225..b219c4970 100644 --- a/src/xprt_qstrm.c +++ b/src/xprt_qstrm.c @@ -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;