From: Matus Fabian Date: Fri, 25 Jul 2025 15:50:00 +0000 (-0400) Subject: http: validate h2 frame lengeth in handlers X-Git-Tag: v26.02-rc0~150 X-Git-Url: https://gerrit.fd.io/r/gitweb?a=commitdiff_plain;h=refs%2Fchanges%2F80%2F43480%2F3;p=vpp.git http: validate h2 frame lengeth in handlers Type: fix Change-Id: I741a80a44c4355849e354c9b17d9213ac90a381d Signed-off-by: Matus Fabian --- diff --git a/src/plugins/http/http2/frame.c b/src/plugins/http/http2/frame.c index fe593a00150..c6551ee48b1 100644 --- a/src/plugins/http/http2/frame.c +++ b/src/plugins/http/http2/frame.c @@ -131,14 +131,12 @@ http2_frame_write_settings (http2_settings_entry_t *settings, u8 **dst) } } -#define WINDOW_UPDATE_LENGTH 4 - __clib_export http2_error_t http2_frame_read_window_update (u32 *increment, u8 *payload, u32 payload_len) { u32 *value; - if (payload_len != WINDOW_UPDATE_LENGTH) + if (payload_len != HTTP2_WINDOW_UPDATE_LENGTH) return HTTP2_ERROR_FRAME_SIZE_ERROR; value = (u32 *) payload; @@ -159,24 +157,22 @@ http2_frame_write_window_update (u32 increment, u32 stream_id, u8 **dst) ASSERT (increment > 0 && increment <= 0x7FFFFFFF); http2_frame_header_t fh = { .type = HTTP2_FRAME_TYPE_WINDOW_UPDATE, - .length = WINDOW_UPDATE_LENGTH, + .length = HTTP2_WINDOW_UPDATE_LENGTH, .stream_id = stream_id }; p = http2_frame_header_alloc (dst); http2_frame_header_write (&fh, p); - vec_add2 (*dst, p, WINDOW_UPDATE_LENGTH); + vec_add2 (*dst, p, HTTP2_WINDOW_UPDATE_LENGTH); value = clib_host_to_net_u32 (increment); - clib_memcpy_fast (p, &value, WINDOW_UPDATE_LENGTH); + clib_memcpy_fast (p, &value, HTTP2_WINDOW_UPDATE_LENGTH); } -#define RST_STREAM_LENGTH 4 - __clib_export http2_error_t http2_frame_read_rst_stream (u32 *error_code, u8 *payload, u32 payload_len) { u32 *value; - if (payload_len != RST_STREAM_LENGTH) + if (payload_len != HTTP2_RST_STREAM_LENGTH) return HTTP2_ERROR_FRAME_SIZE_ERROR; value = (u32 *) payload; @@ -195,14 +191,14 @@ http2_frame_write_rst_stream (http2_error_t error_code, u32 stream_id, ASSERT (stream_id > 0 && stream_id <= 0x7FFFFFFF); http2_frame_header_t fh = { .type = HTTP2_FRAME_TYPE_RST_STREAM, - .length = RST_STREAM_LENGTH, + .length = HTTP2_RST_STREAM_LENGTH, .stream_id = stream_id }; p = http2_frame_header_alloc (dst); http2_frame_header_write (&fh, p); - vec_add2 (*dst, p, RST_STREAM_LENGTH); + vec_add2 (*dst, p, HTTP2_RST_STREAM_LENGTH); value = clib_host_to_net_u32 ((u32) error_code); - clib_memcpy_fast (p, &value, RST_STREAM_LENGTH); + clib_memcpy_fast (p, &value, HTTP2_RST_STREAM_LENGTH); } __clib_export http2_error_t diff --git a/src/plugins/http/http2/frame.h b/src/plugins/http/http2/frame.h index e19cfa7a698..cfa3e850a69 100644 --- a/src/plugins/http/http2/frame.h +++ b/src/plugins/http/http2/frame.h @@ -12,6 +12,8 @@ #define HTTP2_FRAME_HEADER_SIZE 9 #define HTTP2_PING_PAYLOAD_LEN 8 #define HTTP2_GOAWAY_MIN_SIZE 8 +#define HTTP2_WINDOW_UPDATE_LENGTH 4 +#define HTTP2_RST_STREAM_LENGTH 4 #define foreach_http2_frame_type \ _ (0x00, DATA, "DATA") \ diff --git a/src/plugins/http/http2/http2.c b/src/plugins/http/http2/http2.c index 4a3ccf37bd2..d92d52a047c 100644 --- a/src/plugins/http/http2/http2.c +++ b/src/plugins/http/http2/http2.c @@ -1885,6 +1885,12 @@ http2_handle_headers_frame (http_conn_t *hc, http2_frame_header_t *fh) http2_error_t rv; http2_conn_ctx_t *h2c; + if (fh->length < 1) + { + HTTP_DBG (1, "zero length payload"); + return HTTP2_ERROR_FRAME_SIZE_ERROR; + } + h2c = http2_conn_ctx_get_w_thread (hc); if (hc->flags & HTTP_CONN_F_IS_SERVER) @@ -2025,6 +2031,12 @@ http2_handle_continuation_frame (http_conn_t *hc, http2_frame_header_t *fh) u8 *p; http2_error_t rv = HTTP2_ERROR_NO_ERROR; + if (fh->length < 1) + { + HTTP_DBG (1, "zero length payload"); + return HTTP2_ERROR_FRAME_SIZE_ERROR; + } + h2c = http2_conn_ctx_get_w_thread (hc); if (!(h2c->flags & HTTP2_CONN_F_EXPECT_CONTINUATION)) @@ -2141,6 +2153,12 @@ http2_handle_data_frame (http_conn_t *hc, http2_frame_header_t *fh) HTTP2_STREAM_STATE_CLOSED; } + if (fh->length == 0) + { + HTTP_DBG (1, "zero length payload"); + return HTTP2_ERROR_NO_ERROR; + } + rx_buf = http_get_rx_buf (hc); vec_validate (rx_buf, fh->length - 1); http_io_ts_read (hc, rx_buf, fh->length, 0); @@ -2169,6 +2187,12 @@ http2_handle_window_update_frame (http_conn_t *hc, http2_frame_header_t *fh) http2_req_t *req; http2_conn_ctx_t *h2c; + if (fh->length != HTTP2_WINDOW_UPDATE_LENGTH) + { + HTTP_DBG (1, "invalid payload length"); + return HTTP2_ERROR_FRAME_SIZE_ERROR; + } + h2c = http2_conn_ctx_get_w_thread (hc); rx_buf = http_get_rx_buf (hc); @@ -2327,6 +2351,12 @@ http2_handle_rst_stream_frame (http_conn_t *hc, http2_frame_header_t *fh) u32 error_code; http2_conn_ctx_t *h2c; + if (fh->length != HTTP2_RST_STREAM_LENGTH) + { + HTTP_DBG (1, "invalid payload length"); + return HTTP2_ERROR_FRAME_SIZE_ERROR; + } + if (fh->stream_id == 0) return HTTP2_ERROR_PROTOCOL_ERROR; @@ -2370,6 +2400,12 @@ http2_handle_goaway_frame (http_conn_t *hc, http2_frame_header_t *fh) http2_conn_ctx_t *h2c; http2_req_t *req; + if (fh->length < HTTP2_GOAWAY_MIN_SIZE) + { + HTTP_DBG (1, "invalid payload length"); + return HTTP2_ERROR_FRAME_SIZE_ERROR; + } + if (fh->stream_id != 0) return HTTP2_ERROR_PROTOCOL_ERROR;