batman-adv: Merge bugfixes from 2018.1-maint 2018-06-03 381/head
authorSven Eckelmann <sven@narfation.org>
Sun, 3 Jun 2018 13:52:30 +0000 (15:52 +0200)
committerSven Eckelmann <sven@narfation.org>
Sun, 3 Jun 2018 16:42:04 +0000 (18:42 +0200)
* Avoid race in TT TVLV allocator helper
* Fix TT sync flags for intermediate TT responses
* prevent TT request storms by not sending inconsistent TT TLVLs
* Fix bat_ogm_iv best gw refcnt after netlink dump
* Fix bat_v best gw refcnt after netlink dump
* Fix debugfs path for renamed hardif
* Fix debugfs path for renamed softif

Signed-off-by: Sven Eckelmann <sven@narfation.org>
batman-adv/Makefile
batman-adv/patches/0037-batman-adv-Avoid-race-in-TT-TVLV-allocator-helper.patch [new file with mode: 0644]
batman-adv/patches/0038-batman-adv-Fix-TT-sync-flags-for-intermediate-TT-res.patch [new file with mode: 0644]
batman-adv/patches/0039-batman-adv-prevent-TT-request-storms-by-not-sending-.patch [new file with mode: 0644]
batman-adv/patches/0040-batman-adv-Fix-bat_ogm_iv-best-gw-refcnt-after-netli.patch [new file with mode: 0644]
batman-adv/patches/0041-batman-adv-Fix-bat_v-best-gw-refcnt-after-netlink-du.patch [new file with mode: 0644]
batman-adv/patches/0042-batman-adv-Fix-debugfs-path-for-renamed-hardif.patch [new file with mode: 0644]
batman-adv/patches/0043-batman-adv-Fix-debugfs-path-for-renamed-softif.patch [new file with mode: 0644]

index 246fa9840e8da90bb5d6c2f8ccd0b006d0fef2d1..01866985b65435d15a35550bcf049f8c86607e29 100644 (file)
@@ -11,7 +11,7 @@ include $(TOPDIR)/rules.mk
 PKG_NAME:=batman-adv
 
 PKG_VERSION:=2016.5
-PKG_RELEASE:=7
+PKG_RELEASE:=8
 PKG_MD5SUM:=6717a933a08dd2a01b00df30cb9f16a8
 PKG_HASH:=d0a0fc90c4f410b57d043215e253bb0b855efa5edbe165d87c17bfdcfafd0db7
 
diff --git a/batman-adv/patches/0037-batman-adv-Avoid-race-in-TT-TVLV-allocator-helper.patch b/batman-adv/patches/0037-batman-adv-Avoid-race-in-TT-TVLV-allocator-helper.patch
new file mode 100644 (file)
index 0000000..964089e
--- /dev/null
@@ -0,0 +1,75 @@
+From: Sven Eckelmann <sven@narfation.org>
+Date: Wed, 9 May 2018 21:07:40 +0200
+Subject: [PATCH] batman-adv: Avoid race in TT TVLV allocator helper
+
+The functions batadv_tt_prepare_tvlv_local_data and
+batadv_tt_prepare_tvlv_global_data are responsible for preparing a buffer
+which can be used to store the TVLV container for TT and add the VLAN
+information to it.
+
+This will be done in three phases:
+
+1. count the number of VLANs and their entries
+2. allocate the buffer using the counters from the previous step and limits
+   from the caller (parameter tt_len)
+3. insert the VLAN information to the buffer
+
+The step 1 and 3 operate on a list which contains the VLANs. The access to
+these lists must be protected with an appropriate lock or otherwise they
+might operate on on different entries. This could for example happen when
+another context is adding VLAN entries to this list.
+
+This could lead to a buffer overflow in these functions when enough entries
+were added between step 1 and 3 to the VLAN lists that the buffer room for
+the entries (*tt_change) is smaller then the now required extra buffer for
+new VLAN entries.
+
+Fixes: 21a57f6e7a3b ("batman-adv: make the TT CRC logic VLAN specific")
+Signed-off-by: Sven Eckelmann <sven@narfation.org>
+Acked-by: Antonio Quartulli <a@unstable.cc>
+
+Origin: upstream, https://git.open-mesh.org/batman-adv.git/commit/286be89a33497ba9000aa5c2960f1f4114953522
+---
+ net/batman-adv/translation-table.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c
+index a64003b824e0d0b05f0a9e44ccc32ba0cb3018fc..933ac64b5707846ddee9f828b538ade86b968986 100644
+--- a/net/batman-adv/translation-table.c
++++ b/net/batman-adv/translation-table.c
+@@ -860,7 +860,7 @@ batadv_tt_prepare_tvlv_global_data(struct batadv_orig_node *orig_node,
+       struct batadv_orig_node_vlan *vlan;
+       u8 *tt_change_ptr;
+-      rcu_read_lock();
++      spin_lock_bh(&orig_node->vlan_list_lock);
+       hlist_for_each_entry_rcu(vlan, &orig_node->vlan_list, list) {
+               num_vlan++;
+               num_entries += atomic_read(&vlan->tt.num_entries);
+@@ -898,7 +898,7 @@ batadv_tt_prepare_tvlv_global_data(struct batadv_orig_node *orig_node,
+       *tt_change = (struct batadv_tvlv_tt_change *)tt_change_ptr;
+ out:
+-      rcu_read_unlock();
++      spin_unlock_bh(&orig_node->vlan_list_lock);
+       return tvlv_len;
+ }
+@@ -934,7 +934,7 @@ batadv_tt_prepare_tvlv_local_data(struct batadv_priv *bat_priv,
+       u8 *tt_change_ptr;
+       int change_offset;
+-      rcu_read_lock();
++      spin_lock_bh(&bat_priv->softif_vlan_list_lock);
+       hlist_for_each_entry_rcu(vlan, &bat_priv->softif_vlan_list, list) {
+               num_vlan++;
+               num_entries += atomic_read(&vlan->tt.num_entries);
+@@ -972,7 +972,7 @@ batadv_tt_prepare_tvlv_local_data(struct batadv_priv *bat_priv,
+       *tt_change = (struct batadv_tvlv_tt_change *)tt_change_ptr;
+ out:
+-      rcu_read_unlock();
++      spin_unlock_bh(&bat_priv->softif_vlan_list_lock);
+       return tvlv_len;
+ }
diff --git a/batman-adv/patches/0038-batman-adv-Fix-TT-sync-flags-for-intermediate-TT-res.patch b/batman-adv/patches/0038-batman-adv-Fix-TT-sync-flags-for-intermediate-TT-res.patch
new file mode 100644 (file)
index 0000000..cec2fd8
--- /dev/null
@@ -0,0 +1,180 @@
+From: Linus Lüssing <linus.luessing@c0d3.blue>
+Date: Thu, 10 May 2018 19:44:28 +0200
+Subject: [PATCH] batman-adv: Fix TT sync flags for intermediate TT responses
+
+The previous TT sync fix so far only fixed TT responses issued by the
+target node directly. So far, TT responses issued by intermediate nodes
+still lead to the wrong flags being added, leading to CRC mismatches.
+
+This behaviour was observed at Freifunk Hannover in a 800 nodes setup
+where a considerable amount of nodes were still infected with 'WI'
+TT flags even with (most) nodes having the previous TT sync fix applied.
+
+I was able to reproduce the issue with intermediate TT responses in a
+four node test setup and this patch fixes this issue by ensuring to
+use the per originator instead of the summarized, OR'd ones.
+
+Fixes: fa614fd04692 ("batman-adv: fix tt_global_entries flags update")
+Signed-off-by: Linus Lüssing <linus.luessing@c0d3.blue>
+Signed-off-by: Sven Eckelmann <sven@narfation.org>
+
+Origin: backport, https://git.open-mesh.org/batman-adv.git/commit/d65daee8617b29c1ddcc949ce3a5ec24f7a1e1af
+---
+ net/batman-adv/translation-table.c | 61 +++++++++++++++++++++++++-----
+ 1 file changed, 51 insertions(+), 10 deletions(-)
+
+diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c
+index 933ac64b5707846ddee9f828b538ade86b968986..94527e5e859dcdb443b2fc9c3fbbe06aae3b4a08 100644
+--- a/net/batman-adv/translation-table.c
++++ b/net/batman-adv/translation-table.c
+@@ -1528,6 +1528,8 @@ batadv_tt_global_orig_entry_find(const struct batadv_tt_global_entry *entry,
+  *  by a given originator
+  * @entry: the TT global entry to check
+  * @orig_node: the originator to search in the list
++ * @flags: a pointer to store TT flags for the given @entry received
++ *  from @orig_node
+  *
+  * find out if an orig_node is already in the list of a tt_global_entry.
+  *
+@@ -1535,7 +1537,8 @@ batadv_tt_global_orig_entry_find(const struct batadv_tt_global_entry *entry,
+  */
+ static bool
+ batadv_tt_global_entry_has_orig(const struct batadv_tt_global_entry *entry,
+-                              const struct batadv_orig_node *orig_node)
++                              const struct batadv_orig_node *orig_node,
++                              u8 *flags)
+ {
+       struct batadv_tt_orig_list_entry *orig_entry;
+       bool found = false;
+@@ -1543,6 +1546,10 @@ batadv_tt_global_entry_has_orig(const struct batadv_tt_global_entry *entry,
+       orig_entry = batadv_tt_global_orig_entry_find(entry, orig_node);
+       if (orig_entry) {
+               found = true;
++
++              if (flags)
++                      *flags = orig_entry->flags;
++
+               batadv_tt_orig_list_entry_put(orig_entry);
+       }
+@@ -1721,7 +1728,7 @@ static bool batadv_tt_global_add(struct batadv_priv *bat_priv,
+                       if (!(common->flags & BATADV_TT_CLIENT_TEMP))
+                               goto out;
+                       if (batadv_tt_global_entry_has_orig(tt_global_entry,
+-                                                          orig_node))
++                                                          orig_node, NULL))
+                               goto out_remove;
+                       batadv_tt_global_del_orig_list(tt_global_entry);
+                       goto add_orig_entry;
+@@ -2863,23 +2870,46 @@ unlock:
+ }
+ /**
+- * batadv_tt_local_valid - verify that given tt entry is a valid one
++ * batadv_tt_local_valid() - verify local tt entry and get flags
+  * @entry_ptr: to be checked local tt entry
+  * @data_ptr: not used but definition required to satisfy the callback prototype
++ * @flags: a pointer to store TT flags for this client to
++ *
++ * Checks the validity of the given local TT entry. If it is, then the provided
++ * flags pointer is updated.
+  *
+  * Return: true if the entry is a valid, false otherwise.
+  */
+-static bool batadv_tt_local_valid(const void *entry_ptr, const void *data_ptr)
++static bool batadv_tt_local_valid(const void *entry_ptr,
++                                const void *data_ptr,
++                                u8 *flags)
+ {
+       const struct batadv_tt_common_entry *tt_common_entry = entry_ptr;
+       if (tt_common_entry->flags & BATADV_TT_CLIENT_NEW)
+               return false;
++
++      if (flags)
++              *flags = tt_common_entry->flags;
++
+       return true;
+ }
++/**
++ * batadv_tt_global_valid() - verify global tt entry and get flags
++ * @entry_ptr: to be checked global tt entry
++ * @data_ptr: an orig_node object (may be NULL)
++ * @flags: a pointer to store TT flags for this client to
++ *
++ * Checks the validity of the given global TT entry. If it is, then the provided
++ * flags pointer is updated either with the common (summed) TT flags if data_ptr
++ * is NULL or the specific, per originator TT flags otherwise.
++ *
++ * Return: true if the entry is a valid, false otherwise.
++ */
+ static bool batadv_tt_global_valid(const void *entry_ptr,
+-                                 const void *data_ptr)
++                                 const void *data_ptr,
++                                 u8 *flags)
+ {
+       const struct batadv_tt_common_entry *tt_common_entry = entry_ptr;
+       const struct batadv_tt_global_entry *tt_global_entry;
+@@ -2893,7 +2923,8 @@ static bool batadv_tt_global_valid(const void *entry_ptr,
+                                      struct batadv_tt_global_entry,
+                                      common);
+-      return batadv_tt_global_entry_has_orig(tt_global_entry, orig_node);
++      return batadv_tt_global_entry_has_orig(tt_global_entry, orig_node,
++                                             flags);
+ }
+ /**
+@@ -2903,25 +2934,34 @@ static bool batadv_tt_global_valid(const void *entry_ptr,
+  * @hash: hash table containing the tt entries
+  * @tt_len: expected tvlv tt data buffer length in number of bytes
+  * @tvlv_buff: pointer to the buffer to fill with the TT data
+- * @valid_cb: function to filter tt change entries
++ * @valid_cb: function to filter tt change entries and to return TT flags
+  * @cb_data: data passed to the filter function as argument
++ *
++ * Fills the tvlv buff with the tt entries from the specified hash. If valid_cb
++ * is not provided then this becomes a no-op.
+  */
+ static void batadv_tt_tvlv_generate(struct batadv_priv *bat_priv,
+                                   struct batadv_hashtable *hash,
+                                   void *tvlv_buff, u16 tt_len,
+                                   bool (*valid_cb)(const void *,
+-                                                   const void *),
++                                                   const void *,
++                                                   u8 *flags),
+                                   void *cb_data)
+ {
+       struct batadv_tt_common_entry *tt_common_entry;
+       struct batadv_tvlv_tt_change *tt_change;
+       struct hlist_head *head;
+       u16 tt_tot, tt_num_entries = 0;
++      u8 flags;
++      bool ret;
+       u32 i;
+       tt_tot = batadv_tt_entries(tt_len);
+       tt_change = (struct batadv_tvlv_tt_change *)tvlv_buff;
++      if (!valid_cb)
++              return;
++
+       rcu_read_lock();
+       for (i = 0; i < hash->size; i++) {
+               head = &hash->table[i];
+@@ -2931,11 +2971,12 @@ static void batadv_tt_tvlv_generate(struct batadv_priv *bat_priv,
+                       if (tt_tot == tt_num_entries)
+                               break;
+-                      if ((valid_cb) && (!valid_cb(tt_common_entry, cb_data)))
++                      ret = valid_cb(tt_common_entry, cb_data, &flags);
++                      if (!ret)
+                               continue;
+                       ether_addr_copy(tt_change->addr, tt_common_entry->addr);
+-                      tt_change->flags = tt_common_entry->flags;
++                      tt_change->flags = flags;
+                       tt_change->vid = htons(tt_common_entry->vid);
+                       memset(tt_change->reserved, 0,
+                              sizeof(tt_change->reserved));
diff --git a/batman-adv/patches/0039-batman-adv-prevent-TT-request-storms-by-not-sending-.patch b/batman-adv/patches/0039-batman-adv-prevent-TT-request-storms-by-not-sending-.patch
new file mode 100644 (file)
index 0000000..c0f33fc
--- /dev/null
@@ -0,0 +1,76 @@
+From: Marek Lindner <mareklindner@neomailbox.ch>
+Date: Sat, 12 May 2018 00:23:07 +0800
+Subject: [PATCH] batman-adv: prevent TT request storms by not sending inconsistent TT TLVLs
+
+A translation table TVLV changset sent with an OGM consists
+of a number of headers (one per VLAN) plus the changeset
+itself (addition and/or deletion of entries).
+
+The per-VLAN headers are used by OGM recipients for consistency
+checks. Said consistency check might determine that a full
+translation table request is needed to restore consistency. If
+the TT sender adds per-VLAN headers of empty VLANs into the OGM,
+recipients are led to believe to have reached an inconsistent
+state and thus request a full table update. The full table does
+not contain empty VLANs (due to missing entries) the cycle
+restarts when the next OGM is issued.
+
+Consequently, when the translation table TVLV headers are
+composed, empty VLANs are to be excluded.
+
+Fixes: 21a57f6e7a3b ("batman-adv: make the TT CRC logic VLAN specific")
+Signed-off-by: Marek Lindner <mareklindner@neomailbox.ch>
+Signed-off-by: Sven Eckelmann <sven@narfation.org>
+
+Origin: upstream, https://git.open-mesh.org/batman-adv.git/commit/e4687b4be274da6180fc15b327419851fb681ec9
+---
+ net/batman-adv/translation-table.c | 15 ++++++++++++---
+ 1 file changed, 12 insertions(+), 3 deletions(-)
+
+diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c
+index 94527e5e859dcdb443b2fc9c3fbbe06aae3b4a08..743963bf39dca73f7554f9f85fffd57fd6a3c963 100644
+--- a/net/batman-adv/translation-table.c
++++ b/net/batman-adv/translation-table.c
+@@ -929,15 +929,20 @@ batadv_tt_prepare_tvlv_local_data(struct batadv_priv *bat_priv,
+       struct batadv_tvlv_tt_vlan_data *tt_vlan;
+       struct batadv_softif_vlan *vlan;
+       u16 num_vlan = 0;
+-      u16 num_entries = 0;
++      u16 vlan_entries = 0;
++      u16 total_entries = 0;
+       u16 tvlv_len;
+       u8 *tt_change_ptr;
+       int change_offset;
+       spin_lock_bh(&bat_priv->softif_vlan_list_lock);
+       hlist_for_each_entry_rcu(vlan, &bat_priv->softif_vlan_list, list) {
++              vlan_entries = atomic_read(&vlan->tt.num_entries);
++              if (vlan_entries < 1)
++                      continue;
++
+               num_vlan++;
+-              num_entries += atomic_read(&vlan->tt.num_entries);
++              total_entries += vlan_entries;
+       }
+       change_offset = sizeof(**tt_data);
+@@ -945,7 +950,7 @@ batadv_tt_prepare_tvlv_local_data(struct batadv_priv *bat_priv,
+       /* if tt_len is negative, allocate the space needed by the full table */
+       if (*tt_len < 0)
+-              *tt_len = batadv_tt_len(num_entries);
++              *tt_len = batadv_tt_len(total_entries);
+       tvlv_len = *tt_len;
+       tvlv_len += change_offset;
+@@ -962,6 +967,10 @@ batadv_tt_prepare_tvlv_local_data(struct batadv_priv *bat_priv,
+       tt_vlan = (struct batadv_tvlv_tt_vlan_data *)(*tt_data + 1);
+       hlist_for_each_entry_rcu(vlan, &bat_priv->softif_vlan_list, list) {
++              vlan_entries = atomic_read(&vlan->tt.num_entries);
++              if (vlan_entries < 1)
++                      continue;
++
+               tt_vlan->vid = htons(vlan->vid);
+               tt_vlan->crc = htonl(vlan->tt.crc);
diff --git a/batman-adv/patches/0040-batman-adv-Fix-bat_ogm_iv-best-gw-refcnt-after-netli.patch b/batman-adv/patches/0040-batman-adv-Fix-bat_ogm_iv-best-gw-refcnt-after-netli.patch
new file mode 100644 (file)
index 0000000..1b1d12a
--- /dev/null
@@ -0,0 +1,47 @@
+From: Sven Eckelmann <sven@narfation.org>
+Date: Sat, 2 Jun 2018 17:26:34 +0200
+Subject: [PATCH] batman-adv: Fix bat_ogm_iv best gw refcnt after netlink dump
+
+A reference for the best gateway is taken when the list of gateways in the
+mesh is sent via netlink. This is necessary to check whether the currently
+dumped entry is the currently selected gateway or not. This information is
+then transferred as flag BATADV_ATTR_FLAG_BEST.
+
+After the comparison of the current entry is done,
+batadv_iv_gw_dump_entry() has to decrease the reference counter again.
+Otherwise the reference will be held and thus prevents a proper shutdown of
+the batman-adv interfaces (and some of the interfaces enslaved in it).
+
+Fixes: fa3228924152 ("batman-adv: add B.A.T.M.A.N. IV bat_gw_dump implementations")
+Reported-by: Andreas Ziegler <dev@andreas-ziegler.de>
+Tested-by: Andreas Ziegler <dev@andreas-ziegler.de>
+Signed-off-by: Sven Eckelmann <sven@narfation.org>
+Acked-by: Marek Lindner <mareklindner@neomailbox.ch>
+
+Origin: upstream, https://git.open-mesh.org/batman-adv.git/commit/46360d203c627e71a27d1f8f551c819c7f2353fd
+---
+ net/batman-adv/bat_iv_ogm.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c
+index bf389adbb2694746d6397a0a38353cdcd8008899..f0174a17b30d14e5c127106b364b8fbc8ec384ee 100644
+--- a/net/batman-adv/bat_iv_ogm.c
++++ b/net/batman-adv/bat_iv_ogm.c
+@@ -2722,7 +2722,7 @@ static int batadv_iv_gw_dump_entry(struct sk_buff *msg, u32 portid, u32 seq,
+ {
+       struct batadv_neigh_ifinfo *router_ifinfo = NULL;
+       struct batadv_neigh_node *router;
+-      struct batadv_gw_node *curr_gw;
++      struct batadv_gw_node *curr_gw = NULL;
+       int ret = 0;
+       void *hdr;
+@@ -2770,6 +2770,8 @@ static int batadv_iv_gw_dump_entry(struct sk_buff *msg, u32 portid, u32 seq,
+       ret = 0;
+ out:
++      if (curr_gw)
++              batadv_gw_node_put(curr_gw);
+       if (router_ifinfo)
+               batadv_neigh_ifinfo_put(router_ifinfo);
+       if (router)
diff --git a/batman-adv/patches/0041-batman-adv-Fix-bat_v-best-gw-refcnt-after-netlink-du.patch b/batman-adv/patches/0041-batman-adv-Fix-bat_v-best-gw-refcnt-after-netlink-du.patch
new file mode 100644 (file)
index 0000000..3c7a456
--- /dev/null
@@ -0,0 +1,45 @@
+From: Sven Eckelmann <sven@narfation.org>
+Date: Sat, 2 Jun 2018 17:26:35 +0200
+Subject: [PATCH] batman-adv: Fix bat_v best gw refcnt after netlink dump
+
+A reference for the best gateway is taken when the list of gateways in the
+mesh is sent via netlink. This is necessary to check whether the currently
+dumped entry is the currently selected gateway or not. This information is
+then transferred as flag BATADV_ATTR_FLAG_BEST.
+
+After the comparison of the current entry is done,
+batadv_v_gw_dump_entry() has to decrease the reference counter again.
+Otherwise the reference will be held and thus prevents a proper shutdown of
+the batman-adv interfaces (and some of the interfaces enslaved in it).
+
+Fixes: 15315a94ad98 ("batman-adv: add B.A.T.M.A.N. V bat_gw_dump implementations")
+Signed-off-by: Sven Eckelmann <sven@narfation.org>
+Acked-by: Marek Lindner <mareklindner@neomailbox.ch>
+
+Origin: upstream, https://git.open-mesh.org/batman-adv.git/commit/2b422b5808183d1084b450b89d9a085a13dd6d2c
+---
+ net/batman-adv/bat_v.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/net/batman-adv/bat_v.c b/net/batman-adv/bat_v.c
+index 0488063ff6ac5985e27c3a0df41ab3566b48abb8..87f06e92270b4c51376bc4e9717b0aed8c9f3441 100644
+--- a/net/batman-adv/bat_v.c
++++ b/net/batman-adv/bat_v.c
+@@ -929,7 +929,7 @@ static int batadv_v_gw_dump_entry(struct sk_buff *msg, u32 portid, u32 seq,
+ {
+       struct batadv_neigh_ifinfo *router_ifinfo = NULL;
+       struct batadv_neigh_node *router;
+-      struct batadv_gw_node *curr_gw;
++      struct batadv_gw_node *curr_gw = NULL;
+       int ret = 0;
+       void *hdr;
+@@ -997,6 +997,8 @@ static int batadv_v_gw_dump_entry(struct sk_buff *msg, u32 portid, u32 seq,
+       ret = 0;
+ out:
++      if (curr_gw)
++              batadv_gw_node_put(curr_gw);
+       if (router_ifinfo)
+               batadv_neigh_ifinfo_put(router_ifinfo);
+       if (router)
diff --git a/batman-adv/patches/0042-batman-adv-Fix-debugfs-path-for-renamed-hardif.patch b/batman-adv/patches/0042-batman-adv-Fix-debugfs-path-for-renamed-hardif.patch
new file mode 100644 (file)
index 0000000..14ef995
--- /dev/null
@@ -0,0 +1,111 @@
+From: Sven Eckelmann <sven@narfation.org>
+Date: Fri, 1 Jun 2018 19:24:23 +0200
+Subject: [PATCH] batman-adv: Fix debugfs path for renamed hardif
+
+batman-adv is creating special debugfs directories in the init
+net_namespace for each valid hard-interface (net_device). But it is
+possible to rename a net_device to a completely different name then the
+original one.
+
+It can therefore happen that a user registers a new net_device which gets
+the name "wlan0" assigned by default. batman-adv is also adding a new
+directory under $debugfs/batman-adv/ with the name "wlan0".
+
+The user then decides to rename this device to "wl_pri" and registers a
+different device. The kernel may now decide to use the name "wlan0" again
+for this new device. batman-adv will detect it as a valid net_device and
+tries to create a directory with the name "wlan0" under
+$debugfs/batman-adv/. But there already exists one with this name under
+this path and thus this fails. batman-adv will detect a problem and
+rollback the registering of this device.
+
+batman-adv must therefore take care of renaming the debugfs directories
+for hard-interfaces whenever it detects such a net_device rename.
+
+Fixes: 3c926a01c8e8 ("batman-adv: add debugfs structure for information per interface")
+Reported-by: John Soros <sorosj@gmail.com>
+Signed-off-by: Sven Eckelmann <sven@narfation.org>
+
+Origin: backport, https://git.open-mesh.org/batman-adv.git/commit/127086f503f6495518b95455efebee33d328f335
+---
+ net/batman-adv/debugfs.c        | 20 ++++++++++++++++++++
+ net/batman-adv/debugfs.h        |  6 ++++++
+ net/batman-adv/hard-interface.c |  3 +++
+ 3 files changed, 29 insertions(+)
+
+diff --git a/net/batman-adv/debugfs.c b/net/batman-adv/debugfs.c
+index 77925504379dac7d64777393ddae326b5d6d9505..a229d2d9acfd1f3d6fea071aa0df3bf06a0e2ecf 100644
+--- a/net/batman-adv/debugfs.c
++++ b/net/batman-adv/debugfs.c
+@@ -18,6 +18,7 @@
+ #include "debugfs.h"
+ #include "main.h"
++#include <linux/dcache.h>
+ #include <linux/debugfs.h>
+ #include <linux/device.h>
+ #include <linux/errno.h>
+@@ -337,6 +338,25 @@ out:
+       return -ENOMEM;
+ }
++/**
++ * batadv_debugfs_rename_hardif() - Fix debugfs path for renamed hardif
++ * @hard_iface: hard interface which was renamed
++ */
++void batadv_debugfs_rename_hardif(struct batadv_hard_iface *hard_iface)
++{
++      const char *name = hard_iface->net_dev->name;
++      struct dentry *dir;
++      struct dentry *d;
++
++      dir = hard_iface->debug_dir;
++      if (!dir)
++              return;
++
++      d = debugfs_rename(dir->d_parent, dir, dir->d_parent, name);
++      if (!d)
++              pr_err("Can't rename debugfs dir to %s\n", name);
++}
++
+ /**
+  * batadv_debugfs_del_hardif - delete the base directory for a hard interface
+  *  in debugfs.
+diff --git a/net/batman-adv/debugfs.h b/net/batman-adv/debugfs.h
+index e49121ee55f696547ddc9774ba6c425af2d49b57..3d9b684b862d0aa9d2380fbcb15fd4ef68a4511c 100644
+--- a/net/batman-adv/debugfs.h
++++ b/net/batman-adv/debugfs.h
+@@ -31,6 +31,7 @@ void batadv_debugfs_destroy(void);
+ int batadv_debugfs_add_meshif(struct net_device *dev);
+ void batadv_debugfs_del_meshif(struct net_device *dev);
+ int batadv_debugfs_add_hardif(struct batadv_hard_iface *hard_iface);
++void batadv_debugfs_rename_hardif(struct batadv_hard_iface *hard_iface);
+ void batadv_debugfs_del_hardif(struct batadv_hard_iface *hard_iface);
+ #else
+@@ -58,6 +59,11 @@ int batadv_debugfs_add_hardif(struct batadv_hard_iface *hard_iface)
+       return 0;
+ }
++static inline
++void batadv_debugfs_rename_hardif(struct batadv_hard_iface *hard_iface)
++{
++}
++
+ static inline
+ void batadv_debugfs_del_hardif(struct batadv_hard_iface *hard_iface)
+ {
+diff --git a/net/batman-adv/hard-interface.c b/net/batman-adv/hard-interface.c
+index ebeea5816a06b33c4944b01e40cee157c88bdff7..507eaff8582a8c58adc6d23abc42bb6c31d2816f 100644
+--- a/net/batman-adv/hard-interface.c
++++ b/net/batman-adv/hard-interface.c
+@@ -1020,6 +1020,9 @@ static int batadv_hard_if_event(struct notifier_block *this,
+               if (batadv_is_wifi_hardif(hard_iface))
+                       hard_iface->num_bcasts = BATADV_NUM_BCASTS_WIRELESS;
+               break;
++      case NETDEV_CHANGENAME:
++              batadv_debugfs_rename_hardif(hard_iface);
++              break;
+       default:
+               break;
+       }
diff --git a/batman-adv/patches/0043-batman-adv-Fix-debugfs-path-for-renamed-softif.patch b/batman-adv/patches/0043-batman-adv-Fix-debugfs-path-for-renamed-softif.patch
new file mode 100644 (file)
index 0000000..2420ada
--- /dev/null
@@ -0,0 +1,139 @@
+From: Sven Eckelmann <sven@narfation.org>
+Date: Fri, 1 Jun 2018 19:24:24 +0200
+Subject: [PATCH] batman-adv: Fix debugfs path for renamed softif
+
+batman-adv is creating special debugfs directories in the init
+net_namespace for each created soft-interface (batadv net_device). But it
+is possible to rename a net_device to a completely different name then the
+original one.
+
+It can therefore happen that a user registers a new batadv net_device with
+the name "bat0". batman-adv is then also adding a new directory under
+$debugfs/batman-adv/ with the name "wlan0".
+
+The user then decides to rename this device to "bat1" and registers a
+different batadv device with the name "bat0". batman-adv will then try to
+create a directory with the name "bat0" under $debugfs/batman-adv/ again.
+But there already exists one with this name under this path and thus this
+fails. batman-adv will detect a problem and rollback the registering of
+this device.
+
+batman-adv must therefore take care of renaming the debugfs directories for
+soft-interfaces whenever it detects such a net_device rename.
+
+Fixes: 230202d4b530 ("batman-adv: Move device for icmp injection to debugfs")
+Signed-off-by: Sven Eckelmann <sven@narfation.org>
+
+Origin: backport, https://git.open-mesh.org/batman-adv.git/commit/3f2237bb191cd17654a4d5a5badfd6e7379c4b37
+---
+ net/batman-adv/debugfs.c        | 20 +++++++++++++++++++
+ net/batman-adv/debugfs.h        |  5 +++++
+ net/batman-adv/hard-interface.c | 34 +++++++++++++++++++++++++++------
+ 3 files changed, 53 insertions(+), 6 deletions(-)
+
+diff --git a/net/batman-adv/debugfs.c b/net/batman-adv/debugfs.c
+index a229d2d9acfd1f3d6fea071aa0df3bf06a0e2ecf..fa396394edd02e74f49323216027f4ef9739dfa0 100644
+--- a/net/batman-adv/debugfs.c
++++ b/net/batman-adv/debugfs.c
+@@ -421,6 +421,26 @@ out:
+       return -ENOMEM;
+ }
++/**
++ * batadv_debugfs_rename_meshif() - Fix debugfs path for renamed softif
++ * @dev: net_device which was renamed
++ */
++void batadv_debugfs_rename_meshif(struct net_device *dev)
++{
++      struct batadv_priv *bat_priv = netdev_priv(dev);
++      const char *name = dev->name;
++      struct dentry *dir;
++      struct dentry *d;
++
++      dir = bat_priv->debug_dir;
++      if (!dir)
++              return;
++
++      d = debugfs_rename(dir->d_parent, dir, dir->d_parent, name);
++      if (!d)
++              pr_err("Can't rename debugfs dir to %s\n", name);
++}
++
+ void batadv_debugfs_del_meshif(struct net_device *dev)
+ {
+       struct batadv_priv *bat_priv = netdev_priv(dev);
+diff --git a/net/batman-adv/debugfs.h b/net/batman-adv/debugfs.h
+index 3d9b684b862d0aa9d2380fbcb15fd4ef68a4511c..59a0d6d70ecd4d0b49e15138306acc371da2d8b7 100644
+--- a/net/batman-adv/debugfs.h
++++ b/net/batman-adv/debugfs.h
+@@ -29,6 +29,7 @@ struct net_device;
+ void batadv_debugfs_init(void);
+ void batadv_debugfs_destroy(void);
+ int batadv_debugfs_add_meshif(struct net_device *dev);
++void batadv_debugfs_rename_meshif(struct net_device *dev);
+ void batadv_debugfs_del_meshif(struct net_device *dev);
+ int batadv_debugfs_add_hardif(struct batadv_hard_iface *hard_iface);
+ void batadv_debugfs_rename_hardif(struct batadv_hard_iface *hard_iface);
+@@ -49,6 +50,10 @@ static inline int batadv_debugfs_add_meshif(struct net_device *dev)
+       return 0;
+ }
++static inline void batadv_debugfs_rename_meshif(struct net_device *dev)
++{
++}
++
+ static inline void batadv_debugfs_del_meshif(struct net_device *dev)
+ {
+ }
+diff --git a/net/batman-adv/hard-interface.c b/net/batman-adv/hard-interface.c
+index 507eaff8582a8c58adc6d23abc42bb6c31d2816f..23d3893264f989c9740e68d83f6db300dee20dc3 100644
+--- a/net/batman-adv/hard-interface.c
++++ b/net/batman-adv/hard-interface.c
+@@ -958,6 +958,32 @@ void batadv_hardif_remove_interfaces(void)
+       rtnl_unlock();
+ }
++/**
++ * batadv_hard_if_event_softif() - Handle events for soft interfaces
++ * @event: NETDEV_* event to handle
++ * @net_dev: net_device which generated an event
++ *
++ * Return: NOTIFY_* result
++ */
++static int batadv_hard_if_event_softif(unsigned long event,
++                                     struct net_device *net_dev)
++{
++      struct batadv_priv *bat_priv;
++
++      switch (event) {
++      case NETDEV_REGISTER:
++              batadv_sysfs_add_meshif(net_dev);
++              bat_priv = netdev_priv(net_dev);
++              batadv_softif_create_vlan(bat_priv, BATADV_NO_FLAGS);
++              break;
++      case NETDEV_CHANGENAME:
++              batadv_debugfs_rename_meshif(net_dev);
++              break;
++      }
++
++      return NOTIFY_DONE;
++}
++
+ static int batadv_hard_if_event(struct notifier_block *this,
+                               unsigned long event, void *ptr)
+ {
+@@ -966,12 +992,8 @@ static int batadv_hard_if_event(struct notifier_block *this,
+       struct batadv_hard_iface *primary_if = NULL;
+       struct batadv_priv *bat_priv;
+-      if (batadv_softif_is_valid(net_dev) && event == NETDEV_REGISTER) {
+-              batadv_sysfs_add_meshif(net_dev);
+-              bat_priv = netdev_priv(net_dev);
+-              batadv_softif_create_vlan(bat_priv, BATADV_NO_FLAGS);
+-              return NOTIFY_DONE;
+-      }
++      if (batadv_softif_is_valid(net_dev))
++              return batadv_hard_if_event_softif(event, net_dev);
+       hard_iface = batadv_hardif_get_by_netdev(net_dev);
+       if (!hard_iface && (event == NETDEV_REGISTER ||