From: Christopher Faulet Date: Thu, 31 Mar 2022 17:27:18 +0000 (+0200) Subject: MEDIUM: conn-stream: Be prepared to fail to attach a cs to a mux X-Git-Tag: v2.6-dev6~69 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=070b91bc11d1a4c4b2266b9e3bd82efb90918a3c;p=thirdparty%2Fhaproxy.git MEDIUM: conn-stream: Be prepared to fail to attach a cs to a mux To be able to move wait_event from the stream-interface to the conn-stream, we must be prepare to handle errors when a mux is attached to a conn-stream. Indeed, the wait_event's tasklet will be allocated when both a mux and a stream will be both attached to a stream. So, we must be prepared to handle allocation errors. --- diff --git a/include/haproxy/conn_stream.h b/include/haproxy/conn_stream.h index 98921aae58..441146989e 100644 --- a/include/haproxy/conn_stream.h +++ b/include/haproxy/conn_stream.h @@ -46,7 +46,7 @@ struct conn_stream *cs_new_from_strm(struct stream *strm, unsigned int flags); struct conn_stream *cs_new_from_check(struct check *check, unsigned int flags); void cs_free(struct conn_stream *cs); -void cs_attach_mux(struct conn_stream *cs, void *target, void *ctx); +int cs_attach_mux(struct conn_stream *cs, void *target, void *ctx); void cs_attach_applet(struct conn_stream *cs, void *target, void *ctx); int cs_attach_strm(struct conn_stream *cs, struct stream *strm); diff --git a/src/backend.c b/src/backend.c index ea27b8c4a0..65ded4bd1c 100644 --- a/src/backend.c +++ b/src/backend.c @@ -1611,7 +1611,10 @@ skip_reuse: return SF_ERR_INTERNAL; /* how did we get there ? */ } - cs_attach_mux(s->csb, NULL, srv_conn); + if (cs_attach_mux(s->csb, NULL, srv_conn) < 0) { + conn_free(srv_conn); + return SF_ERR_INTERNAL; /* how did we get there ? */ + } srv_conn->ctx = s->csb; #if defined(USE_OPENSSL) && defined(TLSEXT_TYPE_application_layer_protocol_negotiation) diff --git a/src/conn_stream.c b/src/conn_stream.c index 31979d881e..b632912916 100644 --- a/src/conn_stream.c +++ b/src/conn_stream.c @@ -161,7 +161,7 @@ void cs_free(struct conn_stream *cs) /* Attaches a conn_stream to an mux endpoint and sets the endpoint ctx */ -void cs_attach_mux(struct conn_stream *cs, void *target, void *ctx) +int cs_attach_mux(struct conn_stream *cs, void *target, void *ctx) { struct connection *conn = ctx; @@ -177,6 +177,7 @@ void cs_attach_mux(struct conn_stream *cs, void *target, void *ctx) } else if (cs_check(cs)) cs->data_cb = &check_conn_cb; + return 0; } /* Attaches a conn_stream to an applet endpoint and sets the endpoint ctx */ diff --git a/src/mux_fcgi.c b/src/mux_fcgi.c index d34b1c5ecc..5996e7e22a 100644 --- a/src/mux_fcgi.c +++ b/src/mux_fcgi.c @@ -1134,7 +1134,8 @@ static struct fcgi_strm *fcgi_conn_stream_new(struct fcgi_conn *fconn, struct co TRACE_ERROR("fstream allocation failure", FCGI_EV_FSTRM_NEW|FCGI_EV_FSTRM_END|FCGI_EV_FSTRM_ERR, fconn->conn); goto out; } - cs_attach_mux(cs, fstrm, fconn->conn); + if (cs_attach_mux(cs, fstrm, fconn->conn) < 0) + goto out; fstrm->cs = cs; fstrm->endp = cs->endp; fstrm->sess = sess; @@ -1145,6 +1146,7 @@ static struct fcgi_strm *fcgi_conn_stream_new(struct fcgi_conn *fconn, struct co out: TRACE_DEVEL("leaving on error", FCGI_EV_FSTRM_NEW|FCGI_EV_FSTRM_END|FCGI_EV_FSTRM_ERR, fconn->conn); + fcgi_strm_destroy(fstrm); return NULL; } diff --git a/src/mux_h1.c b/src/mux_h1.c index bbdddf9a4e..d7fd3da8f8 100644 --- a/src/mux_h1.c +++ b/src/mux_h1.c @@ -814,7 +814,8 @@ static struct h1s *h1c_frt_stream_new(struct h1c *h1c, struct conn_stream *cs, s goto fail; if (cs) { - cs_attach_mux(cs, h1s, h1c->conn); + if (cs_attach_mux(cs, h1s, h1c->conn) < 0) + goto fail; h1s->cs = cs; h1s->endp = cs->endp; } @@ -853,7 +854,9 @@ static struct h1s *h1c_bck_stream_new(struct h1c *h1c, struct conn_stream *cs, s if (!h1s) goto fail; - cs_attach_mux(cs, h1s, h1c->conn); + if (cs_attach_mux(cs, h1s, h1c->conn) < 0) + goto fail; + h1s->flags |= H1S_F_RX_BLK; h1s->cs = cs; h1s->endp = cs->endp; @@ -872,6 +875,7 @@ static struct h1s *h1c_bck_stream_new(struct h1c *h1c, struct conn_stream *cs, s fail: TRACE_DEVEL("leaving on error", H1_EV_STRM_NEW|H1_EV_STRM_ERR, h1c->conn); + pool_free(pool_head_h1s, h1s); return NULL; } diff --git a/src/mux_h2.c b/src/mux_h2.c index b161278b5f..d39de94094 100644 --- a/src/mux_h2.c +++ b/src/mux_h2.c @@ -1675,7 +1675,11 @@ static struct h2s *h2c_bck_stream_new(struct h2c *h2c, struct conn_stream *cs, s if (!h2s) goto out; - cs_attach_mux(cs, h2s, h2c->conn); + if (cs_attach_mux(cs, h2s, h2c->conn) < 0) { + h2s_destroy(h2s); + h2s = NULL; + goto out; + } h2s->cs = cs; h2s->endp = cs->endp; h2s->sess = sess; diff --git a/src/mux_pt.c b/src/mux_pt.c index 2b1c30d661..97b3b835da 100644 --- a/src/mux_pt.c +++ b/src/mux_pt.c @@ -315,7 +315,8 @@ static int mux_pt_init(struct connection *conn, struct proxy *prx, struct sessio TRACE_POINT(PT_EV_STRM_NEW, conn, cs); } else { - cs_attach_mux(cs, ctx, conn); + if (cs_attach_mux(cs, ctx, conn) < 0) + goto fail_free_ctx; ctx->endp = cs->endp; } conn->ctx = ctx; @@ -385,7 +386,8 @@ static int mux_pt_attach(struct connection *conn, struct conn_stream *cs, struct TRACE_ENTER(PT_EV_STRM_NEW, conn); if (ctx->wait_event.events) conn->xprt->unsubscribe(ctx->conn, conn->xprt_ctx, SUB_RETRY_RECV, &ctx->wait_event); - cs_attach_mux(cs, ctx, conn); + if (cs_attach_mux(cs, ctx, conn) < 0) + return -1; ctx->cs = cs; ctx->endp = cs->endp; ctx->endp->flags |= CS_EP_RCV_MORE; diff --git a/src/tcpcheck.c b/src/tcpcheck.c index 930735b70d..0ac825e060 100644 --- a/src/tcpcheck.c +++ b/src/tcpcheck.c @@ -1101,7 +1101,13 @@ enum tcpcheck_eval_ret tcpcheck_eval_connect(struct check *check, struct tcpchec TRACE_ERROR("conn-stream allocation error", CHK_EV_TCPCHK_CONN|CHK_EV_TCPCHK_ERR, check); goto out; } - cs_attach_mux(check->cs, NULL, conn); + if (cs_attach_mux(check->cs, NULL, conn) < 0) { + TRACE_ERROR("mux attach error", CHK_EV_TCPCHK_CONN|CHK_EV_TCPCHK_ERR, check); + conn_free(conn); + conn = NULL; + status = SF_ERR_RESOURCE; + goto fail_check; + } conn->ctx = check->cs; tasklet_set_tid(check->wait_list.tasklet, tid); conn_set_owner(conn, check->sess, NULL);