From: Amaury Denoyelle Date: Wed, 27 Apr 2022 12:41:53 +0000 (+0200) Subject: BUG/MEDIUM: h3: fix use-after-free on mux Rx buffer wrapping X-Git-Tag: v2.6-dev8~42 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=30f23f53d237ade95910352922a4b17d5b358fa8;p=thirdparty%2Fhaproxy.git BUG/MEDIUM: h3: fix use-after-free on mux Rx buffer wrapping Handle wrapping buffer in h3_data_to_htx(). If data is wrapping, first copy the contiguous data, then copy the data in front of the buffer. Note that h3_headers_to_htx() is not able to handle wrapping data. For the moment, a BUG_ON was added as a reminder. This cas never happened, most probably because HEADERS is the first frame of the stream. --- diff --git a/src/h3.c b/src/h3.c index 9f1e09b465..e516a470c6 100644 --- a/src/h3.c +++ b/src/h3.c @@ -112,6 +112,8 @@ static int h3_headers_to_htx(struct qcs *qcs, struct buffer *buf, uint64_t len, struct ist authority = IST_NULL; int hdr_idx; + /* TODO support buffer wrapping */ + BUG_ON(b_contig_data(buf, 0) != b_data(buf)); if (qpack_decode_fs((const unsigned char *)b_head(buf), len, tmp, list) < 0) return 1; @@ -198,23 +200,31 @@ static int h3_data_to_htx(struct qcs *qcs, struct buffer *buf, uint64_t len, { struct buffer *appbuf; struct htx *htx = NULL; - size_t htx_sent; + size_t contig = 0, htx_sent = 0; int htx_space; + char *head; appbuf = qc_get_buf(qcs, &qcs->rx.app_buf); BUG_ON(!appbuf); htx = htx_from_buf(appbuf); + retry: htx_space = htx_free_data_space(htx); if (!htx_space || htx_space < len) { ABORT_NOW(); /* TODO handle this case properly */ } - htx_sent = htx_add_data(htx, ist2(b_head(buf), len)); - if (htx_sent < len) { - ABORT_NOW(); /* TODO handle this case properly */ + contig = b_contig_data(buf, contig); + if (len > contig) { + htx_sent = htx_add_data(htx, ist2(b_head(buf), contig)); + head = b_orig(buf); + len -= contig; + goto retry; } + htx_sent += htx_add_data(htx, ist2(head, len)); + BUG_ON(htx_sent < len); + if (fin) htx->flags |= HTX_FL_EOM; htx_to_buf(htx, appbuf);