acl: fix the integer overflow bug in API message length validation logic
[vpp.git] / src / plugins / acl / acl.c
index b18e851..dcca2a2 100644 (file)
@@ -216,7 +216,8 @@ static void
     ntohs (VL_API_ACL_PLUGIN_GET_CONN_TABLE_MAX_ENTRIES_REPLY +
           am->msg_id_base);
   rmp->context = mp->context;
-  rmp->conn_table_max_entries = __bswap_64 (am->fa_conn_table_max_entries);
+  rmp->conn_table_max_entries =
+    clib_net_to_host_u64 (am->fa_conn_table_max_entries);
 
   vl_api_send_msg (rp, (u8 *) rmp);
 }
@@ -320,8 +321,13 @@ acl_add_list (u32 count, vl_api_acl_rule_t rules[],
   acl_list_t *a;
   acl_rule_t *r;
   acl_rule_t *acl_new_rules = 0;
+  size_t tag_len;
   int i;
 
+  tag_len = clib_strnlen ((const char *) tag, sizeof (a->tag));
+  if (tag_len == sizeof (a->tag))
+    return VNET_API_ERROR_INVALID_VALUE;
+
   if (am->trace_acl > 255)
     clib_warning ("API dbg: acl_add_list index %d tag %s", *acl_list_index,
                  tag);
@@ -399,7 +405,7 @@ acl_add_list (u32 count, vl_api_acl_rule_t rules[],
        vec_free (a->rules);
     }
   a->rules = acl_new_rules;
-  memcpy (a->tag, tag, sizeof (a->tag));
+  memcpy (a->tag, tag, tag_len + 1);
   if (am->trace_acl > 255)
     warning_acl_print_acl (am->vlib_main, am, *acl_list_index);
   if (am->reclassify_sessions)
@@ -679,7 +685,7 @@ acl_interface_set_inout_acl_list (acl_main_t * am, u32 sw_if_index,
                  seen_acl_bitmap, format_bitmap_hex, change_acl_bitmap);
 
 /* *INDENT-OFF* */
-  clib_bitmap_foreach(acln, change_acl_bitmap, ({
+  clib_bitmap_foreach (acln, change_acl_bitmap)  {
     if (clib_bitmap_get(old_seen_acl_bitmap, acln)) {
       /* ACL is being removed. */
       if (acln < vec_len((*pinout_sw_if_index_vec_by_acl))) {
@@ -691,7 +697,7 @@ acl_interface_set_inout_acl_list (acl_main_t * am, u32 sw_if_index,
       vec_validate((*pinout_sw_if_index_vec_by_acl), acln);
       vec_add1((*pinout_sw_if_index_vec_by_acl)[acln], sw_if_index);
     }
-  }));
+  }
 /* *INDENT-ON* */
 
   vec_free ((*pinout_acl_vec_by_sw_if_index)[sw_if_index]);
@@ -1548,9 +1554,14 @@ macip_acl_add_list (u32 count, vl_api_macip_acl_rule_t rules[],
   macip_acl_list_t *a;
   macip_acl_rule_t *r;
   macip_acl_rule_t *acl_new_rules = 0;
+  size_t tag_len;
   int i;
   int rv = 0;
 
+  tag_len = clib_strnlen ((const char *) tag, sizeof (a->tag));
+  if (tag_len == sizeof (a->tag))
+    return VNET_API_ERROR_INVALID_VALUE;
+
   if (*acl_list_index != ~0)
     {
       /* They supplied some number, let's see if this MACIP ACL exists */
@@ -1609,7 +1620,7 @@ macip_acl_add_list (u32 count, vl_api_macip_acl_rule_t rules[],
 
   a->rules = acl_new_rules;
   a->count = count;
-  memcpy (a->tag, tag, sizeof (a->tag));
+  memcpy (a->tag, tag, tag_len + 1);
 
   /* Create and populate the classifier tables */
   macip_create_classify_tables (am, *acl_list_index);
@@ -1761,7 +1772,7 @@ macip_acl_interface_add_del_acl (u32 sw_if_index, u8 is_add,
  *
  */
 static int
-verify_message_len (void *mp, u32 expected_len, char *where)
+verify_message_len (void *mp, u64 expected_len, char *where)
 {
   u32 supplied_len = vl_msg_api_get_msg_length (mp);
   if (supplied_len < expected_len)
@@ -1785,7 +1796,7 @@ vl_api_acl_add_replace_t_handler (vl_api_acl_add_replace_t * mp)
   int rv;
   u32 acl_list_index = ntohl (mp->acl_index);
   u32 acl_count = ntohl (mp->count);
-  u32 expected_len = sizeof (*mp) + acl_count * sizeof (mp->r[0]);
+  u64 expected_len = sizeof (*mp) + acl_count * sizeof (mp->r[0]);
 
   if (verify_message_len (mp, expected_len, "acl_add_replace"))
     {
@@ -1936,7 +1947,7 @@ send_acl_details (acl_main_t * am, vl_api_registration_t * reg,
   mp->context = context;
   mp->count = htonl (vec_len (acl_rules));
   mp->acl_index = htonl (acl - am->acls);
-  memcpy (mp->tag, acl->tag, sizeof (mp->tag));
+  snprintf ((char *) mp->tag, sizeof (mp->tag), "%s", acl->tag);
   // clib_memcpy (mp->r, acl->rules, acl->count * sizeof(acl->rules[0]));
   rules = mp->r;
   for (i = 0; i < vec_len (acl_rules); i++)
@@ -1965,10 +1976,10 @@ vl_api_acl_dump_t_handler (vl_api_acl_dump_t * mp)
     {
     /* *INDENT-OFF* */
     /* Just dump all ACLs */
-    pool_foreach (acl, am->acls,
-    ({
+    pool_foreach (acl, am->acls)
+     {
       send_acl_details(am, reg, acl, mp->context);
-    }));
+    }
     /* *INDENT-ON* */
     }
   else
@@ -2050,10 +2061,10 @@ vl_api_acl_interface_list_dump_t_handler (vl_api_acl_interface_list_dump_t *
   if (mp->sw_if_index == ~0)
     {
     /* *INDENT-OFF* */
-    pool_foreach (swif, im->sw_interfaces,
-    ({
+    pool_foreach (swif, im->sw_interfaces)
+     {
       send_acl_interface_list_details(am, reg, swif->sw_if_index, mp->context);
-    }));
+    }
     /* *INDENT-ON* */
     }
   else
@@ -2074,7 +2085,7 @@ vl_api_macip_acl_add_t_handler (vl_api_macip_acl_add_t * mp)
   int rv;
   u32 acl_list_index = ~0;
   u32 acl_count = ntohl (mp->count);
-  u32 expected_len = sizeof (*mp) + acl_count * sizeof (mp->r[0]);
+  u64 expected_len = sizeof (*mp) + acl_count * sizeof (mp->r[0]);
 
   if (verify_message_len (mp, expected_len, "macip_acl_add"))
     {
@@ -2101,7 +2112,7 @@ vl_api_macip_acl_add_replace_t_handler (vl_api_macip_acl_add_replace_t * mp)
   int rv;
   u32 acl_list_index = ntohl (mp->acl_index);
   u32 acl_count = ntohl (mp->count);
-  u32 expected_len = sizeof (*mp) + acl_count * sizeof (mp->r[0]);
+  u64 expected_len = sizeof (*mp) + acl_count * sizeof (mp->r[0]);
 
   if (verify_message_len (mp, expected_len, "macip_acl_add_replace"))
     {
@@ -2170,7 +2181,7 @@ send_macip_acl_details (acl_main_t * am, vl_api_registration_t * reg,
   mp->context = context;
   if (acl)
     {
-      memcpy (mp->tag, acl->tag, sizeof (mp->tag));
+      snprintf ((char *) mp->tag, sizeof (mp->tag), "%s", acl->tag);
       mp->count = htonl (acl->count);
       mp->acl_index = htonl (acl - am->macip_acls);
       rules = mp->r;
@@ -2215,10 +2226,10 @@ vl_api_macip_acl_dump_t_handler (vl_api_macip_acl_dump_t * mp)
     {
       /* Just dump all ACLs for now, with sw_if_index = ~0 */
       /* *INDENT-OFF* */
-      pool_foreach (acl, am->macip_acls,
-        ({
+      pool_foreach (acl, am->macip_acls)
+         {
           send_macip_acl_details (am, reg, acl, mp->context);
-        }));
+        }
       /* *INDENT-ON* */
     }
   else
@@ -2424,10 +2435,10 @@ static void
   if (mp->sw_if_index == ~0)
     {
     /* *INDENT-OFF* */
-    pool_foreach (swif, im->sw_interfaces,
-    ({
+    pool_foreach (swif, im->sw_interfaces)
+     {
       send_acl_interface_etype_whitelist_details(am, reg, swif->sw_if_index, mp->context);
-    }));
+    }
     /* *INDENT-ON* */
     }
   else
@@ -2828,7 +2839,7 @@ acl_set_aclplugin_acl_fn (vlib_main_t * vm,
   u32 tcpflags, tcpmask;
   u32 src_prefix_length = 0, dst_prefix_length = 0;
   ip46_address_t src, dst;
-  u8 *tag = (u8 *) "cli";
+  u8 *tag = 0;
 
   if (!unformat_user (input, unformat_line_input, line_input))
     return 0;
@@ -2934,10 +2945,13 @@ acl_set_aclplugin_acl_fn (vlib_main_t * vm,
     }
 
   u32 acl_index = ~0;
+  if (!tag)
+    vec_add (tag, "cli", 4);
 
   rv = acl_add_list (vec_len (rules), rules, &acl_index, tag);
 
   vec_free (rules);
+  vec_free (tag);
 
   if (rv)
     return (clib_error_return (0, "failed"));
@@ -3268,8 +3282,8 @@ acl_plugin_show_sessions (acl_main_t * am,
        }
       vlib_cli_output (vm, "  connection add/del stats:", wk);
       /* *INDENT-OFF* */
-      pool_foreach (swif, im->sw_interfaces,
-        ({
+      pool_foreach (swif, im->sw_interfaces)
+         {
           u32 sw_if_index = swif->sw_if_index;
           u64 n_adds =
             (sw_if_index < vec_len (pw->fa_session_adds_by_sw_if_index) ?
@@ -3291,7 +3305,7 @@ acl_plugin_show_sessions (acl_main_t * am,
                            n_adds -
                            n_dels,
                            n_epoch_changes);
-        }));
+        }
       /* *INDENT-ON* */
 
       vlib_cli_output (vm, "  connection timeout type lists:", wk);