batman-adv: Merge bugfixes from 2018.3
[feed/routing.git] / batman-adv / patches / 0053-batman-adv-Prevent-duplicated-softif_vlan-entry.patch
diff --git a/batman-adv/patches/0053-batman-adv-Prevent-duplicated-softif_vlan-entry.patch b/batman-adv/patches/0053-batman-adv-Prevent-duplicated-softif_vlan-entry.patch
new file mode 100644 (file)
index 0000000..46a68cf
--- /dev/null
@@ -0,0 +1,81 @@
+From: Sven Eckelmann <sven@narfation.org>
+Date: Thu, 6 Sep 2018 14:35:26 +0200
+Subject: [PATCH] batman-adv: Prevent duplicated softif_vlan entry
+
+The function batadv_softif_vlan_get is responsible for adding new
+softif_vlan to the softif_vlan_list. It first checks whether the entry
+already is in the list or not. If it is, then the creation of a new entry
+is aborted.
+
+But the lock for the list is only held when the list is really modified.
+This could lead to duplicated entries because another context could create
+an entry with the same key between the check and the list manipulation.
+
+The check and the manipulation of the list must therefore be in the same
+locked code section.
+
+Fixes: 952cebb57518 ("batman-adv: add per VLAN interface attribute framework")
+Signed-off-by: Sven Eckelmann <sven@narfation.org>
+
+Origin: upstream, https://git.open-mesh.org/batman-adv.git/commit/023d3f64207e8b6a6e6d0718d98e239c5545ef0c
+---
+ net/batman-adv/soft-interface.c | 27 +++++++++++++++++++--------
+ 1 file changed, 19 insertions(+), 8 deletions(-)
+
+diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c
+index 5da1a1c0f1efb5d95f31bc852b899f61e462feb1..ff797f32fb3bb81dafe1e7d3e9c6307e6a5aaff1 100644
+--- a/net/batman-adv/soft-interface.c
++++ b/net/batman-adv/soft-interface.c
+@@ -587,15 +587,20 @@ int batadv_softif_create_vlan(struct batadv_priv *bat_priv, unsigned short vid)
+       struct batadv_softif_vlan *vlan;
+       int err;
++      spin_lock_bh(&bat_priv->softif_vlan_list_lock);
++
+       vlan = batadv_softif_vlan_get(bat_priv, vid);
+       if (vlan) {
+               batadv_softif_vlan_put(vlan);
++              spin_unlock_bh(&bat_priv->softif_vlan_list_lock);
+               return -EEXIST;
+       }
+       vlan = kzalloc(sizeof(*vlan), GFP_ATOMIC);
+-      if (!vlan)
++      if (!vlan) {
++              spin_unlock_bh(&bat_priv->softif_vlan_list_lock);
+               return -ENOMEM;
++      }
+       vlan->bat_priv = bat_priv;
+       vlan->vid = vid;
+@@ -603,17 +608,23 @@ int batadv_softif_create_vlan(struct batadv_priv *bat_priv, unsigned short vid)
+       atomic_set(&vlan->ap_isolation, 0);
+-      err = batadv_sysfs_add_vlan(bat_priv->soft_iface, vlan);
+-      if (err) {
+-              kfree(vlan);
+-              return err;
+-      }
+-
+-      spin_lock_bh(&bat_priv->softif_vlan_list_lock);
+       kref_get(&vlan->refcount);
+       hlist_add_head_rcu(&vlan->list, &bat_priv->softif_vlan_list);
+       spin_unlock_bh(&bat_priv->softif_vlan_list_lock);
++      /* batadv_sysfs_add_vlan cannot be in the spinlock section due to the
++       * sleeping behavior of the sysfs functions and the fs_reclaim lock
++       */
++      err = batadv_sysfs_add_vlan(bat_priv->soft_iface, vlan);
++      if (err) {
++              /* ref for the function */
++              batadv_softif_vlan_put(vlan);
++
++              /* ref for the list */
++              batadv_softif_vlan_put(vlan);
++              return err;
++      }
++
+       /* add a new TT local entry. This one will be marked with the NOPURGE
+        * flag
+        */