From c08dcd3519f75fd65a310cc55f97a3fc1b9c76c9 Mon Sep 17 00:00:00 2001 From: Amaury Denoyelle Date: Thu, 23 Apr 2026 17:32:44 +0200 Subject: [PATCH] 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. --- src/xprt_qstrm.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) 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;