http: validate h2 frame lengeth in handlers 80/43480/3
authorMatus Fabian <[email protected]>
Fri, 25 Jul 2025 15:50:00 +0000 (11:50 -0400)
committerFlorin Coras <[email protected]>
Sat, 26 Jul 2025 03:13:59 +0000 (03:13 +0000)
Type: fix

Change-Id: I741a80a44c4355849e354c9b17d9213ac90a381d
Signed-off-by: Matus Fabian <[email protected]>
src/plugins/http/http2/frame.c
src/plugins/http/http2/frame.h
src/plugins/http/http2/http2.c

index fe593a0..c6551ee 100644 (file)
@@ -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
index e19cfa7..cfa3e85 100644 (file)
@@ -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")                                                      \
index 4a3ccf3..d92d52a 100644 (file)
@@ -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;