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.
This commit is contained in:
Amaury Denoyelle 2026-04-23 17:32:44 +02:00
parent bb016b66c4
commit c08dcd3519

View 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;