batman-adv: Merge bugfixes from 2018.3 414/head
authorSven Eckelmann <sven@narfation.org>
Sat, 15 Sep 2018 09:19:36 +0000 (11:19 +0200)
committerSven Eckelmann <sven@narfation.org>
Sat, 15 Sep 2018 09:19:36 +0000 (11:19 +0200)
* Avoid probe ELP information leak
* Fix segfault when writing to throughput_override
* Fix segfault when writing to sysfs elp_interval
* fix backbone_gw refcount on queue_work() failure
* fix hardif_neigh refcount on queue_work() failure
* Prevent duplicated gateway_node entry
* Prevent duplicated nc_node entry
* Prevent duplicated softif_vlan entry
* Prevent duplicated global TT entry
* Prevent duplicated tvlv handler

Signed-off-by: Sven Eckelmann <sven@narfation.org>
batman-adv/Makefile
batman-adv/patches/0012-batman-adv-Avoid-probe-ELP-information-leak.patch [new file with mode: 0644]
batman-adv/patches/0013-batman-adv-Fix-segfault-when-writing-to-throughput_o.patch [new file with mode: 0644]
batman-adv/patches/0014-batman-adv-Fix-segfault-when-writing-to-sysfs-elp_in.patch [new file with mode: 0644]
batman-adv/patches/0015-batman-adv-fix-backbone_gw-refcount-on-queue_work-fa.patch [new file with mode: 0644]
batman-adv/patches/0016-batman-adv-fix-hardif_neigh-refcount-on-queue_work-f.patch [new file with mode: 0644]
batman-adv/patches/0017-batman-adv-Prevent-duplicated-gateway_node-entry.patch [new file with mode: 0644]
batman-adv/patches/0018-batman-adv-Prevent-duplicated-nc_node-entry.patch [new file with mode: 0644]
batman-adv/patches/0019-batman-adv-Prevent-duplicated-softif_vlan-entry.patch [new file with mode: 0644]
batman-adv/patches/0020-batman-adv-Prevent-duplicated-global-TT-entry.patch [new file with mode: 0644]
batman-adv/patches/0021-batman-adv-Prevent-duplicated-tvlv-handler.patch [new file with mode: 0644]

index bf8b94688a484f45a0800597847803f30c5f182e..b1e3bf2e1bbebb6582a0e4cd0fed74b6f764670f 100644 (file)
@@ -10,7 +10,7 @@ include $(TOPDIR)/rules.mk
 PKG_NAME:=batman-adv
 
 PKG_VERSION:=2018.1
-PKG_RELEASE:=2
+PKG_RELEASE:=3
 PKG_HASH:=b866b28dbbe5c9238abbdf5abbc30fc526dea56898ce4c1bd76d5c017843048b
 
 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
diff --git a/batman-adv/patches/0012-batman-adv-Avoid-probe-ELP-information-leak.patch b/batman-adv/patches/0012-batman-adv-Avoid-probe-ELP-information-leak.patch
new file mode 100644 (file)
index 0000000..83371eb
--- /dev/null
@@ -0,0 +1,35 @@
+From: Sven Eckelmann <sven@narfation.org>
+Date: Fri, 31 Aug 2018 15:08:44 +0200
+Subject: [PATCH] batman-adv: Avoid probe ELP information leak
+
+The probe ELPs for WiFi interfaces are expanded to contain at least
+BATADV_ELP_MIN_PROBE_SIZE bytes. This is usually a lot more than the
+number of bytes which the template ELP packet requires.
+
+These extra padding bytes were not initialized and thus could contain data
+which were previously stored at the same location. It is therefore required
+to set it to some predefined or random values to avoid leaking private
+information from the system transmitting these kind of packets.
+
+Fixes: bedcadfaa92b ("batman-adv: ELP - send unicast ELP packets for throughput sampling")
+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/6c876e572f592c31132a55b5fb8427e168e5fb3c
+---
+ net/batman-adv/bat_v_elp.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/net/batman-adv/bat_v_elp.c b/net/batman-adv/bat_v_elp.c
+index 28687493599f5ba10b8813c18d803582210bc292..371028f82a0669e86155fee39ba955cbbde48e60 100644
+--- a/net/batman-adv/bat_v_elp.c
++++ b/net/batman-adv/bat_v_elp.c
+@@ -228,7 +228,7 @@ batadv_v_elp_wifi_neigh_probe(struct batadv_hardif_neigh_node *neigh)
+                * the packet to be exactly of that size to make the link
+                * throughput estimation effective.
+                */
+-              skb_put(skb, probe_len - hard_iface->bat_v.elp_skb->len);
++              skb_put_zero(skb, probe_len - hard_iface->bat_v.elp_skb->len);
+               batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
+                          "Sending unicast (probe) ELP packet on interface %s to %pM\n",
diff --git a/batman-adv/patches/0013-batman-adv-Fix-segfault-when-writing-to-throughput_o.patch b/batman-adv/patches/0013-batman-adv-Fix-segfault-when-writing-to-throughput_o.patch
new file mode 100644 (file)
index 0000000..4c7d3b0
--- /dev/null
@@ -0,0 +1,45 @@
+From: Sven Eckelmann <sven@narfation.org>
+Date: Fri, 31 Aug 2018 16:46:47 +0200
+Subject: [PATCH] batman-adv: Fix segfault when writing to throughput_override
+
+The per hardif sysfs file "batman_adv/throughput_override" prints the
+resulting change as info text when the users writes to this file. It uses
+the helper function batadv_info to add it at the same time to the kernel
+ring buffer and to the batman-adv debug log (when CONFIG_BATMAN_ADV_DEBUG
+is enabled).
+
+The function batadv_info requires as first parameter the batman-adv softif
+net_device. This parameter is then used to find the private buffer which
+contains the debug log for this batman-adv interface. But
+batadv_store_throughput_override used as first argument the slave
+net_device. This slave device doesn't have the batadv_priv private data
+which is access by batadv_info.
+
+Writing to this file with CONFIG_BATMAN_ADV_DEBUG enabled can either lead
+to a segfault or to memory corruption.
+
+Fixes: c513176e4b7a ("batman-adv: add throughput override attribute to hard_ifaces")
+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/ddf99b78e255530cbadc0f67656a549e19520280
+---
+ net/batman-adv/sysfs.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/net/batman-adv/sysfs.c b/net/batman-adv/sysfs.c
+index f2eef43bd2ec5b798ba552ff14eedcfa734b39d6..3a76e8970c025ca6917d6cd15d1382f685cd3532 100644
+--- a/net/batman-adv/sysfs.c
++++ b/net/batman-adv/sysfs.c
+@@ -1090,8 +1090,9 @@ static ssize_t batadv_store_throughput_override(struct kobject *kobj,
+       if (old_tp_override == tp_override)
+               goto out;
+-      batadv_info(net_dev, "%s: Changing from: %u.%u MBit to: %u.%u MBit\n",
+-                  "throughput_override",
++      batadv_info(hard_iface->soft_iface,
++                  "%s: %s: Changing from: %u.%u MBit to: %u.%u MBit\n",
++                  "throughput_override", net_dev->name,
+                   old_tp_override / 10, old_tp_override % 10,
+                   tp_override / 10, tp_override % 10);
diff --git a/batman-adv/patches/0014-batman-adv-Fix-segfault-when-writing-to-sysfs-elp_in.patch b/batman-adv/patches/0014-batman-adv-Fix-segfault-when-writing-to-sysfs-elp_in.patch
new file mode 100644 (file)
index 0000000..a06f3ba
--- /dev/null
@@ -0,0 +1,108 @@
+From: Sven Eckelmann <sven@narfation.org>
+Date: Fri, 31 Aug 2018 16:56:29 +0200
+Subject: [PATCH] batman-adv: Fix segfault when writing to sysfs elp_interval
+
+The per hardif sysfs file "batman_adv/elp_interval" is using the generic
+functions to store/show uint values. The helper __batadv_store_uint_attr
+requires the softif net_device as parameter to print the resulting change
+as info text when the users writes to this file. It uses the helper
+function batadv_info to add it at the same time to the kernel ring buffer
+and to the batman-adv debug log (when CONFIG_BATMAN_ADV_DEBUG is enabled).
+
+The function batadv_info requires as first parameter the batman-adv softif
+net_device. This parameter is then used to find the private buffer which
+contains the debug log for this batman-adv interface. But
+batadv_store_throughput_override used as first argument the slave
+net_device. This slave device doesn't have the batadv_priv private data
+which is access by batadv_info.
+
+Writing to this file with CONFIG_BATMAN_ADV_DEBUG enabled can either lead
+to a segfault or to memory corruption.
+
+Fixes: ec46535b8275 ("batman-adv: Add hard_iface specific sysfs wrapper macros for UINT")
+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/848be9859b0109a6e428f92f21f2e660153b1c75
+---
+ net/batman-adv/sysfs.c | 25 +++++++++++++++++--------
+ 1 file changed, 17 insertions(+), 8 deletions(-)
+
+diff --git a/net/batman-adv/sysfs.c b/net/batman-adv/sysfs.c
+index 3a76e8970c025ca6917d6cd15d1382f685cd3532..09427fc6494a157554d8b19f3481a878a9f97bba 100644
+--- a/net/batman-adv/sysfs.c
++++ b/net/batman-adv/sysfs.c
+@@ -188,7 +188,8 @@ ssize_t batadv_store_##_name(struct kobject *kobj,                 \
+                                                                       \
+       return __batadv_store_uint_attr(buff, count, _min, _max,        \
+                                       _post_func, attr,               \
+-                                      &bat_priv->_var, net_dev);      \
++                                      &bat_priv->_var, net_dev,       \
++                                      NULL);  \
+ }
+ #define BATADV_ATTR_SIF_SHOW_UINT(_name, _var)                                \
+@@ -262,7 +263,9 @@ ssize_t batadv_store_##_name(struct kobject *kobj,                 \
+                                                                       \
+       length = __batadv_store_uint_attr(buff, count, _min, _max,      \
+                                         _post_func, attr,             \
+-                                        &hard_iface->_var, net_dev);  \
++                                        &hard_iface->_var,            \
++                                        hard_iface->soft_iface,       \
++                                        net_dev);                     \
+                                                                       \
+       batadv_hardif_put(hard_iface);                          \
+       return length;                                                  \
+@@ -356,10 +359,12 @@ __batadv_store_bool_attr(char *buff, size_t count,
+ static int batadv_store_uint_attr(const char *buff, size_t count,
+                                 struct net_device *net_dev,
++                                struct net_device *slave_dev,
+                                 const char *attr_name,
+                                 unsigned int min, unsigned int max,
+                                 atomic_t *attr)
+ {
++      char ifname[IFNAMSIZ + 3] = "";
+       unsigned long uint_val;
+       int ret;
+@@ -385,8 +390,11 @@ static int batadv_store_uint_attr(const char *buff, size_t count,
+       if (atomic_read(attr) == uint_val)
+               return count;
+-      batadv_info(net_dev, "%s: Changing from: %i to: %lu\n",
+-                  attr_name, atomic_read(attr), uint_val);
++      if (slave_dev)
++              snprintf(ifname, sizeof(ifname), "%s: ", slave_dev->name);
++
++      batadv_info(net_dev, "%s: %sChanging from: %i to: %lu\n",
++                  attr_name, ifname, atomic_read(attr), uint_val);
+       atomic_set(attr, uint_val);
+       return count;
+@@ -397,12 +405,13 @@ static ssize_t __batadv_store_uint_attr(const char *buff, size_t count,
+                                       void (*post_func)(struct net_device *),
+                                       const struct attribute *attr,
+                                       atomic_t *attr_store,
+-                                      struct net_device *net_dev)
++                                      struct net_device *net_dev,
++                                      struct net_device *slave_dev)
+ {
+       int ret;
+-      ret = batadv_store_uint_attr(buff, count, net_dev, attr->name, min, max,
+-                                   attr_store);
++      ret = batadv_store_uint_attr(buff, count, net_dev, slave_dev,
++                                   attr->name, min, max, attr_store);
+       if (post_func && ret)
+               post_func(net_dev);
+@@ -571,7 +580,7 @@ static ssize_t batadv_store_gw_sel_class(struct kobject *kobj,
+       return __batadv_store_uint_attr(buff, count, 1, BATADV_TQ_MAX_VALUE,
+                                       batadv_post_gw_reselect, attr,
+                                       &bat_priv->gw.sel_class,
+-                                      bat_priv->soft_iface);
++                                      bat_priv->soft_iface, NULL);
+ }
+ static ssize_t batadv_show_gw_bwidth(struct kobject *kobj,
diff --git a/batman-adv/patches/0015-batman-adv-fix-backbone_gw-refcount-on-queue_work-fa.patch b/batman-adv/patches/0015-batman-adv-fix-backbone_gw-refcount-on-queue_work-fa.patch
new file mode 100644 (file)
index 0000000..e6f43d4
--- /dev/null
@@ -0,0 +1,45 @@
+From: Marek Lindner <mareklindner@neomailbox.ch>
+Date: Fri, 7 Sep 2018 05:45:54 +0800
+Subject: [PATCH] batman-adv: fix backbone_gw refcount on queue_work() failure
+
+The backbone_gw refcounter is to be decreased by the queued work and
+currently is never decreased if the queue_work() call fails.
+Fix by checking the queue_work() return value and decrease refcount
+if necessary.
+
+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/24d83a50421c1c5d39cd9c015516a1a293ae8d0c
+---
+ net/batman-adv/bridge_loop_avoidance.c | 10 ++++++++--
+ 1 file changed, 8 insertions(+), 2 deletions(-)
+
+diff --git a/net/batman-adv/bridge_loop_avoidance.c b/net/batman-adv/bridge_loop_avoidance.c
+index a2de5a44bd41bf5c3d521d29b72e0b225a3ace05..58c093caf49e804c1e11426959d70e79f1729d41 100644
+--- a/net/batman-adv/bridge_loop_avoidance.c
++++ b/net/batman-adv/bridge_loop_avoidance.c
+@@ -1772,6 +1772,7 @@ batadv_bla_loopdetect_check(struct batadv_priv *bat_priv, struct sk_buff *skb,
+ {
+       struct batadv_bla_backbone_gw *backbone_gw;
+       struct ethhdr *ethhdr;
++      bool ret;
+       ethhdr = eth_hdr(skb);
+@@ -1795,8 +1796,13 @@ batadv_bla_loopdetect_check(struct batadv_priv *bat_priv, struct sk_buff *skb,
+       if (unlikely(!backbone_gw))
+               return true;
+-      queue_work(batadv_event_workqueue, &backbone_gw->report_work);
+-      /* backbone_gw is unreferenced in the report work function function */
++      ret = queue_work(batadv_event_workqueue, &backbone_gw->report_work);
++
++      /* backbone_gw is unreferenced in the report work function function
++       * if queue_work() call was successful
++       */
++      if (!ret)
++              batadv_backbone_gw_put(backbone_gw);
+       return true;
+ }
diff --git a/batman-adv/patches/0016-batman-adv-fix-hardif_neigh-refcount-on-queue_work-f.patch b/batman-adv/patches/0016-batman-adv-fix-hardif_neigh-refcount-on-queue_work-f.patch
new file mode 100644 (file)
index 0000000..c0a7195
--- /dev/null
@@ -0,0 +1,43 @@
+From: Marek Lindner <mareklindner@neomailbox.ch>
+Date: Fri, 7 Sep 2018 05:45:55 +0800
+Subject: [PATCH] batman-adv: fix hardif_neigh refcount on queue_work() failure
+
+The hardif_neigh refcounter is to be decreased by the queued work and
+currently is never decreased if the queue_work() call fails.
+Fix by checking the queue_work() return value and decrease refcount
+if necessary.
+
+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/85100b602c127cecf1bcfd620d20eb867d685df2
+---
+ net/batman-adv/bat_v_elp.c | 8 ++++++--
+ 1 file changed, 6 insertions(+), 2 deletions(-)
+
+diff --git a/net/batman-adv/bat_v_elp.c b/net/batman-adv/bat_v_elp.c
+index 371028f82a0669e86155fee39ba955cbbde48e60..83b46654449df72ceda6ca3177f72e7faf0603ab 100644
+--- a/net/batman-adv/bat_v_elp.c
++++ b/net/batman-adv/bat_v_elp.c
+@@ -255,6 +255,7 @@ static void batadv_v_elp_periodic_work(struct work_struct *work)
+       struct batadv_priv *bat_priv;
+       struct sk_buff *skb;
+       u32 elp_interval;
++      bool ret;
+       bat_v = container_of(work, struct batadv_hard_iface_bat_v, elp_wq.work);
+       hard_iface = container_of(bat_v, struct batadv_hard_iface, bat_v);
+@@ -316,8 +317,11 @@ static void batadv_v_elp_periodic_work(struct work_struct *work)
+                * may sleep and that is not allowed in an rcu protected
+                * context. Therefore schedule a task for that.
+                */
+-              queue_work(batadv_event_workqueue,
+-                         &hardif_neigh->bat_v.metric_work);
++              ret = queue_work(batadv_event_workqueue,
++                               &hardif_neigh->bat_v.metric_work);
++
++              if (!ret)
++                      batadv_hardif_neigh_put(hardif_neigh);
+       }
+       rcu_read_unlock();
diff --git a/batman-adv/patches/0017-batman-adv-Prevent-duplicated-gateway_node-entry.patch b/batman-adv/patches/0017-batman-adv-Prevent-duplicated-gateway_node-entry.patch
new file mode 100644 (file)
index 0000000..f456d99
--- /dev/null
@@ -0,0 +1,81 @@
+From: Sven Eckelmann <sven@narfation.org>
+Date: Thu, 6 Sep 2018 14:35:24 +0200
+Subject: [PATCH] batman-adv: Prevent duplicated gateway_node entry
+
+The function batadv_gw_node_add is responsible for adding new gw_node to
+the gateway_list. It is expecting that the caller already checked that
+there is not already an entry with the same key or not.
+
+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: bc3538cabac5 ("batman-adv: adding gateway functionality")
+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/69b3ca714eba608fe79a51ccd89ce7050ee0b770
+---
+ net/batman-adv/gateway_client.c | 11 +++++++++--
+ 1 file changed, 9 insertions(+), 2 deletions(-)
+
+diff --git a/net/batman-adv/gateway_client.c b/net/batman-adv/gateway_client.c
+index 8b198ee798c910b40997ed9ca867fc931c53dcc3..140c61a3f1ecfec4fe23c5ddca19e18e2e86fd56 100644
+--- a/net/batman-adv/gateway_client.c
++++ b/net/batman-adv/gateway_client.c
+@@ -32,6 +32,7 @@
+ #include <linux/kernel.h>
+ #include <linux/kref.h>
+ #include <linux/list.h>
++#include <linux/lockdep.h>
+ #include <linux/netdevice.h>
+ #include <linux/netlink.h>
+ #include <linux/rculist.h>
+@@ -348,6 +349,9 @@ void batadv_gw_check_election(struct batadv_priv *bat_priv,
+  * @bat_priv: the bat priv with all the soft interface information
+  * @orig_node: originator announcing gateway capabilities
+  * @gateway: announced bandwidth information
++ *
++ * Has to be called with the appropriate locks being acquired
++ * (gw.list_lock).
+  */
+ static void batadv_gw_node_add(struct batadv_priv *bat_priv,
+                              struct batadv_orig_node *orig_node,
+@@ -355,6 +359,8 @@ static void batadv_gw_node_add(struct batadv_priv *bat_priv,
+ {
+       struct batadv_gw_node *gw_node;
++      lockdep_assert_held(&bat_priv->gw.list_lock);
++
+       if (gateway->bandwidth_down == 0)
+               return;
+@@ -369,10 +375,8 @@ static void batadv_gw_node_add(struct batadv_priv *bat_priv,
+       gw_node->bandwidth_down = ntohl(gateway->bandwidth_down);
+       gw_node->bandwidth_up = ntohl(gateway->bandwidth_up);
+-      spin_lock_bh(&bat_priv->gw.list_lock);
+       kref_get(&gw_node->refcount);
+       hlist_add_head_rcu(&gw_node->list, &bat_priv->gw.gateway_list);
+-      spin_unlock_bh(&bat_priv->gw.list_lock);
+       batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
+                  "Found new gateway %pM -> gw bandwidth: %u.%u/%u.%u MBit\n",
+@@ -428,11 +432,14 @@ void batadv_gw_node_update(struct batadv_priv *bat_priv,
+ {
+       struct batadv_gw_node *gw_node, *curr_gw = NULL;
++      spin_lock_bh(&bat_priv->gw.list_lock);
+       gw_node = batadv_gw_node_get(bat_priv, orig_node);
+       if (!gw_node) {
+               batadv_gw_node_add(bat_priv, orig_node, gateway);
++              spin_unlock_bh(&bat_priv->gw.list_lock);
+               goto out;
+       }
++      spin_unlock_bh(&bat_priv->gw.list_lock);
+       if (gw_node->bandwidth_down == ntohl(gateway->bandwidth_down) &&
+           gw_node->bandwidth_up == ntohl(gateway->bandwidth_up))
diff --git a/batman-adv/patches/0018-batman-adv-Prevent-duplicated-nc_node-entry.patch b/batman-adv/patches/0018-batman-adv-Prevent-duplicated-nc_node-entry.patch
new file mode 100644 (file)
index 0000000..c1c3103
--- /dev/null
@@ -0,0 +1,90 @@
+From: Sven Eckelmann <sven@narfation.org>
+Date: Thu, 6 Sep 2018 14:35:25 +0200
+Subject: [PATCH] batman-adv: Prevent duplicated nc_node entry
+
+The function batadv_nc_get_nc_node is responsible for adding new nc_nodes
+to the in_coding_list and out_coding_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: 3ed7ada3f0bb ("batman-adv: network coding - detect coding nodes and remove these after timeout")
+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/bab8447ad1850b25188f9652c0c52f8e58acd656
+---
+ net/batman-adv/network-coding.c | 41 ++++++++++++++++++---------------
+ 1 file changed, 22 insertions(+), 19 deletions(-)
+
+diff --git a/net/batman-adv/network-coding.c b/net/batman-adv/network-coding.c
+index c3578444f3cbe759a5385ac460ccb9d41ae1c4de..34caf129a9bf5531360f798be6a7059bad26a50f 100644
+--- a/net/batman-adv/network-coding.c
++++ b/net/batman-adv/network-coding.c
+@@ -854,24 +854,6 @@ batadv_nc_get_nc_node(struct batadv_priv *bat_priv,
+       spinlock_t *lock; /* Used to lock list selected by "int in_coding" */
+       struct list_head *list;
+-      /* Check if nc_node is already added */
+-      nc_node = batadv_nc_find_nc_node(orig_node, orig_neigh_node, in_coding);
+-
+-      /* Node found */
+-      if (nc_node)
+-              return nc_node;
+-
+-      nc_node = kzalloc(sizeof(*nc_node), GFP_ATOMIC);
+-      if (!nc_node)
+-              return NULL;
+-
+-      /* Initialize nc_node */
+-      INIT_LIST_HEAD(&nc_node->list);
+-      kref_init(&nc_node->refcount);
+-      ether_addr_copy(nc_node->addr, orig_node->orig);
+-      kref_get(&orig_neigh_node->refcount);
+-      nc_node->orig_node = orig_neigh_node;
+-
+       /* Select ingoing or outgoing coding node */
+       if (in_coding) {
+               lock = &orig_neigh_node->in_coding_list_lock;
+@@ -881,13 +863,34 @@ batadv_nc_get_nc_node(struct batadv_priv *bat_priv,
+               list = &orig_neigh_node->out_coding_list;
+       }
++      spin_lock_bh(lock);
++
++      /* Check if nc_node is already added */
++      nc_node = batadv_nc_find_nc_node(orig_node, orig_neigh_node, in_coding);
++
++      /* Node found */
++      if (nc_node)
++              goto unlock;
++
++      nc_node = kzalloc(sizeof(*nc_node), GFP_ATOMIC);
++      if (!nc_node)
++              goto unlock;
++
++      /* Initialize nc_node */
++      INIT_LIST_HEAD(&nc_node->list);
++      kref_init(&nc_node->refcount);
++      ether_addr_copy(nc_node->addr, orig_node->orig);
++      kref_get(&orig_neigh_node->refcount);
++      nc_node->orig_node = orig_neigh_node;
++
+       batadv_dbg(BATADV_DBG_NC, bat_priv, "Adding nc_node %pM -> %pM\n",
+                  nc_node->addr, nc_node->orig_node->orig);
+       /* Add nc_node to orig_node */
+-      spin_lock_bh(lock);
+       kref_get(&nc_node->refcount);
+       list_add_tail_rcu(&nc_node->list, list);
++
++unlock:
+       spin_unlock_bh(lock);
+       return nc_node;
diff --git a/batman-adv/patches/0019-batman-adv-Prevent-duplicated-softif_vlan-entry.patch b/batman-adv/patches/0019-batman-adv-Prevent-duplicated-softif_vlan-entry.patch
new file mode 100644 (file)
index 0000000..7cb33f3
--- /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 edeffcb9f3a24e1b53c2b4d705fb260717ac09c4..79d6ab78359db9c6a5df14e2e204c611ab134dfc 100644
+--- a/net/batman-adv/soft-interface.c
++++ b/net/batman-adv/soft-interface.c
+@@ -574,15 +574,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;
+@@ -590,17 +595,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
+        */
diff --git a/batman-adv/patches/0020-batman-adv-Prevent-duplicated-global-TT-entry.patch b/batman-adv/patches/0020-batman-adv-Prevent-duplicated-global-TT-entry.patch
new file mode 100644 (file)
index 0000000..159c653
--- /dev/null
@@ -0,0 +1,59 @@
+From: Sven Eckelmann <sven@narfation.org>
+Date: Thu, 6 Sep 2018 14:35:27 +0200
+Subject: [PATCH] batman-adv: Prevent duplicated global TT entry
+
+The function batadv_tt_global_orig_entry_add is responsible for adding new
+tt_orig_list_entry to the orig_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: c5eb5bb30321 ("batman-adv: add reference counting for type batadv_tt_orig_list_entry")
+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/79097255a1a3e1bd1949be309af941181fbc7b36
+---
+ net/batman-adv/translation-table.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c
+index 12a2b7d21376721d15c6a31f3e794e4270d74b5c..d21624c446655d57786a1bcfa45aaf57c5ce9701 100644
+--- a/net/batman-adv/translation-table.c
++++ b/net/batman-adv/translation-table.c
+@@ -1613,6 +1613,8 @@ batadv_tt_global_orig_entry_add(struct batadv_tt_global_entry *tt_global,
+ {
+       struct batadv_tt_orig_list_entry *orig_entry;
++      spin_lock_bh(&tt_global->list_lock);
++
+       orig_entry = batadv_tt_global_orig_entry_find(tt_global, orig_node);
+       if (orig_entry) {
+               /* refresh the ttvn: the current value could be a bogus one that
+@@ -1635,11 +1637,9 @@ batadv_tt_global_orig_entry_add(struct batadv_tt_global_entry *tt_global,
+       orig_entry->flags = flags;
+       kref_init(&orig_entry->refcount);
+-      spin_lock_bh(&tt_global->list_lock);
+       kref_get(&orig_entry->refcount);
+       hlist_add_head_rcu(&orig_entry->list,
+                          &tt_global->orig_list);
+-      spin_unlock_bh(&tt_global->list_lock);
+       atomic_inc(&tt_global->orig_list_count);
+ sync_flags:
+@@ -1647,6 +1647,8 @@ batadv_tt_global_orig_entry_add(struct batadv_tt_global_entry *tt_global,
+ out:
+       if (orig_entry)
+               batadv_tt_orig_list_entry_put(orig_entry);
++
++      spin_unlock_bh(&tt_global->list_lock);
+ }
+ /**
diff --git a/batman-adv/patches/0021-batman-adv-Prevent-duplicated-tvlv-handler.patch b/batman-adv/patches/0021-batman-adv-Prevent-duplicated-tvlv-handler.patch
new file mode 100644 (file)
index 0000000..5922170
--- /dev/null
@@ -0,0 +1,59 @@
+From: Sven Eckelmann <sven@narfation.org>
+Date: Thu, 6 Sep 2018 14:35:28 +0200
+Subject: [PATCH] batman-adv: Prevent duplicated tvlv handler
+
+The function batadv_tvlv_handler_register is responsible for adding new
+tvlv_handler to the handler_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: 0b6aa0d43767 ("batman-adv: tvlv - basic infrastructure")
+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/acabad79e01740525cf4ff8ce6e9a210b683d420
+---
+ net/batman-adv/tvlv.c | 8 ++++++--
+ 1 file changed, 6 insertions(+), 2 deletions(-)
+
+diff --git a/net/batman-adv/tvlv.c b/net/batman-adv/tvlv.c
+index a637458205d16bf838f796383d8cc15ac861801b..40e69c9346d22c09481544b8b4dec56cad88b64a 100644
+--- a/net/batman-adv/tvlv.c
++++ b/net/batman-adv/tvlv.c
+@@ -529,15 +529,20 @@ void batadv_tvlv_handler_register(struct batadv_priv *bat_priv,
+ {
+       struct batadv_tvlv_handler *tvlv_handler;
++      spin_lock_bh(&bat_priv->tvlv.handler_list_lock);
++
+       tvlv_handler = batadv_tvlv_handler_get(bat_priv, type, version);
+       if (tvlv_handler) {
++              spin_unlock_bh(&bat_priv->tvlv.handler_list_lock);
+               batadv_tvlv_handler_put(tvlv_handler);
+               return;
+       }
+       tvlv_handler = kzalloc(sizeof(*tvlv_handler), GFP_ATOMIC);
+-      if (!tvlv_handler)
++      if (!tvlv_handler) {
++              spin_unlock_bh(&bat_priv->tvlv.handler_list_lock);
+               return;
++      }
+       tvlv_handler->ogm_handler = optr;
+       tvlv_handler->unicast_handler = uptr;
+@@ -547,7 +552,6 @@ void batadv_tvlv_handler_register(struct batadv_priv *bat_priv,
+       kref_init(&tvlv_handler->refcount);
+       INIT_HLIST_NODE(&tvlv_handler->list);
+-      spin_lock_bh(&bat_priv->tvlv.handler_list_lock);
+       kref_get(&tvlv_handler->refcount);
+       hlist_add_head_rcu(&tvlv_handler->list, &bat_priv->tvlv.handler_list);
+       spin_unlock_bh(&bat_priv->tvlv.handler_list_lock);