BUG/MEDIUM: h3: Properly limit the number of headers received
authorChristopher Faulet <cfaulet@haproxy.com>
Wed, 20 Nov 2024 16:20:05 +0000 (17:20 +0100)
committerChristopher Faulet <cfaulet@haproxy.com>
Fri, 22 Nov 2024 14:47:00 +0000 (15:47 +0100)
The number of headers are limited before the decoding but pseudo headers and
cookie headers consume extra slots. In practice, this lowers the maximum number
of headers that can be received.

To workaround this issue, the limit is doubled during the frame decoding to be
sure to have enough extra slots. And the number of headers is tested against the
configured limit after the HTX message was created to be able to report an
error. Unfortunatly no parsing error are reported because the QUIC multiplexer
is not able to do so for now.

The same is performed on trailers to be consistent with H2.

This patch should be backported as far as 2.6.

(cherry picked from commit 785e63335374a6db8ef35205cdb36ea726710061)
Signed-off-by: Christopher Faulet <cfaulet@haproxy.com>

src/h3.c

index 2898b9e..35b9039 100644 (file)
--- a/src/h3.c
+++ b/src/h3.c
@@ -525,7 +525,7 @@ static ssize_t h3_headers_to_htx(struct qcs *qcs, const struct buffer *buf,
        struct buffer *tmp = get_trash_chunk();
        struct htx *htx = NULL;
        struct htx_sl *sl;
-       struct http_hdr list[global.tune.max_http_hdr];
+       struct http_hdr list[global.tune.max_http_hdr * 2];
        unsigned int flags = HTX_SL_F_NONE;
        struct ist meth = IST_NULL, path = IST_NULL;
        struct ist scheme = IST_NULL, authority = IST_NULL;
@@ -898,6 +898,12 @@ static ssize_t h3_headers_to_htx(struct qcs *qcs, const struct buffer *buf,
                }
        }
 
+       /* Check the number of blocks agains "tune.http.maxhdr" value before adding EOH block */
+       if (htx_nbblks(htx) > global.tune.max_http_hdr) {
+               len = -1;
+               goto out;
+       }
+
        if (!htx_add_endof(htx, HTX_BLK_EOH)) {
                len = -1;
                goto out;
@@ -962,7 +968,7 @@ static ssize_t h3_trailers_to_htx(struct qcs *qcs, const struct buffer *buf,
        struct buffer *appbuf = NULL;
        struct htx *htx = NULL;
        struct htx_sl *sl;
-       struct http_hdr list[global.tune.max_http_hdr];
+       struct http_hdr list[global.tune.max_http_hdr * 2];
        int hdr_idx, ret;
        const char *ctl;
        int qpack_err;
@@ -1080,6 +1086,12 @@ static ssize_t h3_trailers_to_htx(struct qcs *qcs, const struct buffer *buf,
                ++hdr_idx;
        }
 
+       /* Check the number of blocks agains "tune.http.maxhdr" value before adding EOT block */
+       if (htx_nbblks(htx) > global.tune.max_http_hdr) {
+               len = -1;
+               goto out;
+       }
+
        if (!htx_add_endof(htx, HTX_BLK_EOT)) {
                TRACE_ERROR("cannot add trailer", H3_EV_RX_FRAME|H3_EV_RX_HDR, qcs->qcc->conn, qcs);
                len = -1;