IGMP: validate the packets length in the DP 30/13430/2
authorNeale Ranns <nranns@cisco.com>
Wed, 11 Jul 2018 16:21:06 +0000 (09:21 -0700)
committerNeale Ranns <nranns@cisco.com>
Thu, 12 Jul 2018 10:26:10 +0000 (10:26 +0000)
thanks to coverity... validate that the length of the packet on
wire matches the size of the header based on the number of groups
and sources. drop those that don't match.

Change-Id: Iab3f3a835f6a43d9c73c5d502ea5ceccdd6985b0
Signed-off-by: Neale Ranns <nranns@cisco.com>
src/plugins/igmp/igmp_input.c
src/plugins/igmp/igmp_query.c
src/plugins/igmp/igmp_report.c

index d4563bf..5f54a0b 100644 (file)
@@ -259,8 +259,8 @@ igmp_parse_query (vlib_main_t * vm, vlib_node_runtime_t * node,
        {
          igmp_membership_query_v3_t *igmp;
          igmp_query_args_t *args;
+         u32 bi, next, len;
          vlib_buffer_t *b;
-         u32 bi, next;
 
          next = IGMP_PARSE_QUERY_NEXT_DROP;
          bi = from[0];
@@ -283,20 +283,29 @@ igmp_parse_query (vlib_main_t * vm, vlib_node_runtime_t * node,
              clib_memcpy (tr->packet_data, vlib_buffer_get_current (b),
                           sizeof (tr->packet_data));
            }
+         len = igmp_membership_query_v3_length (igmp);
 
          /*
-          * copy the contents of the query, and the interface, over
-          * to the main thread for processing
+          * validate that the length on the packet on the wire
+          * corresponds to the length on the calculated v3 query
+          */
+         if (vlib_buffer_length_in_chain (vm, b) == len)
+           {
+             /*
+              * copy the contents of the query, and the interface, over
+              * to the main thread for processing
+              */
+             vlib_buffer_advance (b, -sizeof (u32));
+             args = vlib_buffer_get_current (b);
+             args->sw_if_index = vnet_buffer (b)->sw_if_index[VLIB_RX];
+
+             vl_api_rpc_call_main_thread (igmp_handle_query,
+                                          (u8 *) args, sizeof (*args) + len);
+           }
+         /*
+          * else a packet that is reporting more or less sources
+          * than it really has, bin it
           */
-         vlib_buffer_advance (b, -sizeof (u32));
-         args = vlib_buffer_get_current (b);
-         args->sw_if_index = vnet_buffer (b)->sw_if_index[VLIB_RX];
-
-         vl_api_rpc_call_main_thread (igmp_handle_query,
-                                      (u8 *) args,
-                                      sizeof (*args) +
-                                      igmp_membership_query_v3_length
-                                      (igmp));
 
          vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
                                           n_left_to_next, bi, next);
@@ -351,7 +360,7 @@ igmp_parse_report (vlib_main_t * vm, vlib_node_runtime_t * node,
        {
          igmp_membership_report_v3_t *igmp;
          igmp_report_args_t *args;
-         u32 bi, next;
+         u32 bi, next, len;
          vlib_buffer_t *b;
 
          next = IGMP_PARSE_REPORT_NEXT_DROP;
@@ -368,6 +377,7 @@ igmp_parse_report (vlib_main_t * vm, vlib_node_runtime_t * node,
          error = IGMP_ERROR_NONE;
          b->error = error_node->errors[error];
          igmp = vlib_buffer_get_current (b);
+         len = igmp_membership_report_v3_length (igmp);
 
          ASSERT (igmp->header.type == IGMP_TYPE_membership_report_v3);
 
@@ -382,19 +392,27 @@ igmp_parse_report (vlib_main_t * vm, vlib_node_runtime_t * node,
            }
 
          /*
-          * copy the contents of the query, and the interface, over
-          * to the main thread for processing
+          * validate that the length on the packet on the wire
+          * corresponds to the length on the calculated v3 query
+          */
+         if (vlib_buffer_length_in_chain (vm, b) == len)
+           {
+             /*
+              * copy the contents of the query, and the interface, over
+              * to the main thread for processing
+              */
+             vlib_buffer_advance (b, -sizeof (u32));
+             args = vlib_buffer_get_current (b);
+             args->sw_if_index = vnet_buffer (b)->sw_if_index[VLIB_RX];
+
+             vl_api_rpc_call_main_thread (igmp_handle_report,
+                                          (u8 *) args, sizeof (*args) + len);
+           }
+         /*
+          * else
+          *   this is a packet with more groups/sources than the
+          *   header reports. bin it
           */
-         vlib_buffer_advance (b, -sizeof (u32));
-         args = vlib_buffer_get_current (b);
-         args->sw_if_index = vnet_buffer (b)->sw_if_index[VLIB_RX];
-
-         vl_api_rpc_call_main_thread (igmp_handle_report,
-                                      (u8 *) args,
-                                      sizeof (*args) +
-                                      igmp_membership_report_v3_length
-                                      (igmp));
-
          vlib_validate_buffer_enqueue_x1 (vm, node, next_index, to_next,
                                           n_left_to_next, bi, next);
        }
index 1513023..ae9a4d5 100644 (file)
@@ -36,6 +36,10 @@ igmp_query_mk_source_list (const igmp_membership_query_v3_t * q)
   const ip4_address_t *s;
   u16 ii, n;
 
+  /*
+   * we validated this packet when we accepted it in the DP, so
+   * this number is safe to use
+   */
   n = clib_net_to_host_u16 (q->n_src_addresses);
 
   if (0 == n)
index 328b890..2caa936 100644 (file)
@@ -25,6 +25,10 @@ igmp_group_mk_source_list (const igmp_membership_group_v3_t * r)
   const ip4_address_t *s;
   u16 ii, n;
 
+  /*
+   * we validated this packet when we accepted it in the DP, so
+   * this number is safe to use
+   */
   n = clib_net_to_host_u16 (r->n_src_addresses);
 
   if (0 == n)
@@ -172,6 +176,10 @@ igmp_handle_report (const igmp_report_args_t * args)
       return;
     }
 
+  /*
+   * we validated this packet when we accepted it in the DP, so
+   * this number is safe to use
+   */
   n_groups = clib_net_to_host_u16 (args->report[0].n_groups);
   igmp_group = args->report[0].groups;