nat: deterministic: disallow invalid config 48/27648/3
authorKlement Sekera <ksekera@cisco.com>
Tue, 23 Jun 2020 13:12:33 +0000 (13:12 +0000)
committerOle Trøan <otroan@employees.org>
Wed, 24 Jun 2020 07:20:50 +0000 (07:20 +0000)
Prevent overflow if input network prefix is too small and crash on
packet #1 due to vector not being allocated/initialized.

Type: fix
Signed-off-by: Klement Sekera <ksekera@cisco.com>
Change-Id: I3494cc62ce889df48cc59cc9340b5dd70338c3a8

src/plugins/nat/nat44_cli.c
src/plugins/nat/nat_det.c

index c73cffa..7d74f36 100644 (file)
@@ -1858,8 +1858,13 @@ snat_det_map_command_fn (vlib_main_t * vm,
        }
     }
 
-  rv = snat_det_add_map (sm, &in_addr, (u8) in_plen, &out_addr, (u8) out_plen,
-                        is_add);
+  if (in_plen > 32 || out_plen > 32)
+    {
+      error = clib_error_return (0, "network prefix length must be <= 32");
+      goto done;
+    }
+
+  rv = snat_det_add_map (sm, &in_addr, in_plen, &out_addr, out_plen, is_add);
 
   if (rv)
     {
index 0ab96dc..cad0d2a 100644 (file)
@@ -71,6 +71,17 @@ snat_det_add_map (snat_main_t * sm, ip4_address_t * in_addr, u8 in_plen,
 
   if (is_add)
     {
+      u32 num_sessions = (1 << (32 - in_plen));
+      if (num_sessions > UINT32_MAX / 1000)
+       {
+         // don't let it overflow
+         return VNET_API_ERROR_INVALID_VALUE;
+       }
+      else
+       {
+         num_sessions = num_sessions * 1000 - 1;
+       }
+
       pool_get (sm->det_maps, det_map);
       clib_memset (det_map, 0, sizeof (*det_map));
       det_map->in_addr.as_u32 = in_cmp.as_u32;
@@ -80,9 +91,8 @@ snat_det_add_map (snat_main_t * sm, ip4_address_t * in_addr, u8 in_plen,
       det_map->sharing_ratio = (1 << (32 - in_plen)) / (1 << (32 - out_plen));
       det_map->ports_per_host = (65535 - 1023) / det_map->sharing_ratio;
 
-      vec_validate_init_empty (det_map->sessions,
-                              SNAT_DET_SES_PER_USER * (1 << (32 - in_plen)) -
-                              1, empty_snat_det_session);
+      vec_validate_init_empty (det_map->sessions, num_sessions,
+                              empty_snat_det_session);
     }
   else
     {