linux-cp: fix tap interface attrs in case the sw pool realloc'd 19/35719/3
authorVladislav Grishenko <themiron@yandex-team.ru>
Sun, 20 Mar 2022 10:55:25 +0000 (15:55 +0500)
committerMatthew Smith <mgsmith@netgate.com>
Tue, 29 Mar 2022 15:24:58 +0000 (15:24 +0000)
Creating tap interface / sub interface causes allocation of a new
software interface with possible sw interface pool reallocation.
In such case accessing L3 MTU and interface flags by obsolete sw
pointer is UAF.
Instead, keep desired tap interface MTU value before sw intreface
creation and refetch sw pointer right before sw flags inheritance.

Type: fix
Fixes: b89c1ddcb3b4f9138ca3ebefb2115f896ff3e1bd
Signed-off-by: Vladislav Grishenko <themiron@yandex-team.ru>
Change-Id: I21ea46d146d11060bb9bedc77377ab17ae9e22e8

src/plugins/linux-cp/lcp_interface.c

index bcd8ac7..be73372 100644 (file)
@@ -981,6 +981,7 @@ lcp_itf_pair_create (u32 phy_sw_if_index, u8 *host_if_name,
        .host_namespace = 0,
       };
       ethernet_interface_t *ei;
+      u32 host_sw_mtu_size;
 
       if (host_if_type == LCP_ITF_HOST_TUN)
        args.tap_flags |= TAP_FLAG_TUN;
@@ -990,18 +991,28 @@ lcp_itf_pair_create (u32 phy_sw_if_index, u8 *host_if_name,
          mac_address_copy (&args.host_mac_addr, &ei->address.mac);
        }
 
-      if (sw->mtu[VNET_MTU_L3])
+      /*
+       * The TAP interface does copy forward the host MTU based on the VPP
+       * interface's L3 MTU, but it should also ensure that the VPP tap
+       * interface has an MTU that is greater-or-equal to those. Considering
+       * users can set the interfaces at runtime (set interface mtu packet ...)
+       * ensure that the tap MTU is large enough, taking the VPP interface L3
+       * if it's set, and otherwise a sensible default.
+       */
+      host_sw_mtu_size = sw->mtu[VNET_MTU_L3];
+      if (host_sw_mtu_size)
        {
          args.host_mtu_set = 1;
-         args.host_mtu_size = sw->mtu[VNET_MTU_L3];
+         args.host_mtu_size = host_sw_mtu_size;
        }
+      else
+       host_sw_mtu_size = ETHERNET_MAX_PACKET_BYTES;
 
       if (ns && ns[0] != 0)
        args.host_namespace = ns;
 
       vm = vlib_get_main ();
       tap_create_if (vm, &args);
-
       if (args.rv < 0)
        {
          LCP_ITF_PAIR_ERR ("pair_create: could not create tap, retval:%d",
@@ -1009,20 +1020,7 @@ lcp_itf_pair_create (u32 phy_sw_if_index, u8 *host_if_name,
          return args.rv;
        }
 
-      /*
-       * The TAP interface does copy forward the host MTU based on the VPP
-       * interface's L3 MTU, but it should also ensure that the VPP tap
-       * interface has an MTU that is greater-or-equal to those. Considering
-       * users can set the interfaces at runtime (set interface mtu packet ...)
-       * ensure that the tap MTU is large enough, taking the VPP interface L3
-       * if it's set, and otherwise a sensible default.
-       */
-      if (sw->mtu[VNET_MTU_L3])
-       vnet_sw_interface_set_mtu (vnm, args.sw_if_index,
-                                  sw->mtu[VNET_MTU_L3]);
-      else
-       vnet_sw_interface_set_mtu (vnm, args.sw_if_index,
-                                  ETHERNET_MAX_PACKET_BYTES);
+      vnet_sw_interface_set_mtu (vnm, args.sw_if_index, host_sw_mtu_size);
 
       /*
        * get the hw and ethernet of the tap
@@ -1068,7 +1066,7 @@ lcp_itf_pair_create (u32 phy_sw_if_index, u8 *host_if_name,
    * The TAP is shared by many interfaces, always keep it up.
    * This controls whether the host can RX/TX.
    */
-
+  sw = vnet_get_sw_interface (vnm, phy_sw_if_index);
   lip = lcp_itf_pair_get (lcp_itf_pair_find_by_vif (vif_index));
   LCP_ITF_PAIR_INFO ("pair create: %U sw-flags %u hw-flags %u",
                     format_lcp_itf_pair, lip, sw->flags, hw->flags);