--- /dev/null
+From foo@baz Tue 17 Mar 2020 11:15:43 AM CET
+From: Sven Eckelmann <sven@narfation.org>
+Date: Mon, 16 Mar 2020 23:30:47 +0100
+Subject: batman-adv: Accept only filled wifi station info
+To: stable@vger.kernel.org
+Cc: Sven Eckelmann <sven@narfation.org>, Alvaro Antelo <alvaro.antelo@gmail.com>, Marek Lindner <mareklindner@neomailbox.ch>, Simon Wunderlich <sw@simonwunderlich.de>
+Message-ID: <20200316223105.6333-7-sven@narfation.org>
+
+From: Sven Eckelmann <sven@narfation.org>
+
+commit d62890885efbc48acea46964ea3af69b61c8c5eb upstream.
+
+The wifi driver can decide to not provide parts of the station info. For
+example, the expected throughput of the station can be omitted when the
+used rate control doesn't provide this kind of information.
+
+The B.A.T.M.A.N. V implementation must therefore check the filled bitfield
+before it tries to access the expected_throughput of the returned
+station_info.
+
+Reported-by: Alvaro Antelo <alvaro.antelo@gmail.com>
+Fixes: c833484e5f38 ("batman-adv: ELP - compute the metric based on the estimated throughput")
+Signed-off-by: Sven Eckelmann <sven@narfation.org>
+Reviewed-by: Marek Lindner <mareklindner@neomailbox.ch>
+Signed-off-by: Simon Wunderlich <sw@simonwunderlich.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/batman-adv/bat_v_elp.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/net/batman-adv/bat_v_elp.c
++++ b/net/batman-adv/bat_v_elp.c
+@@ -19,6 +19,7 @@
+ #include "main.h"
+
+ #include <linux/atomic.h>
++#include <linux/bitops.h>
+ #include <linux/byteorder/generic.h>
+ #include <linux/errno.h>
+ #include <linux/etherdevice.h>
+@@ -29,6 +30,7 @@
+ #include <linux/kernel.h>
+ #include <linux/kref.h>
+ #include <linux/netdevice.h>
++#include <linux/nl80211.h>
+ #include <linux/random.h>
+ #include <linux/rculist.h>
+ #include <linux/rcupdate.h>
+@@ -102,6 +104,8 @@ static u32 batadv_v_elp_get_throughput(s
+ }
+ if (ret)
+ goto default_throughput;
++ if (!(sinfo.filled & BIT(NL80211_STA_INFO_EXPECTED_THROUGHPUT)))
++ goto default_throughput;
+
+ return sinfo.expected_throughput / 100;
+ }
--- /dev/null
+From foo@baz Tue 17 Mar 2020 11:15:43 AM CET
+From: Sven Eckelmann <sven@narfation.org>
+Date: Mon, 16 Mar 2020 23:30:50 +0100
+Subject: batman-adv: Always initialize fragment header priority
+To: stable@vger.kernel.org
+Cc: Sven Eckelmann <sven.eckelmann@open-mesh.com>, Simon Wunderlich <sw@simonwunderlich.de>
+Message-ID: <20200316223105.6333-10-sven@narfation.org>
+
+From: Sven Eckelmann <sven.eckelmann@open-mesh.com>
+
+commit fe77d8257c4d838c5976557ddb87bd789f312412 upstream.
+
+The batman-adv unuicast fragment header contains 3 bits for the priority of
+the packet. These bits will be initialized when the skb->priority contains
+a value between 256 and 263. But otherwise, the uninitialized bits from the
+stack will be used.
+
+Fixes: c0f25c802b33 ("batman-adv: Include frame priority in fragment header")
+Signed-off-by: Sven Eckelmann <sven.eckelmann@open-mesh.com>
+Signed-off-by: Simon Wunderlich <sw@simonwunderlich.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/batman-adv/fragmentation.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/net/batman-adv/fragmentation.c
++++ b/net/batman-adv/fragmentation.c
+@@ -484,6 +484,8 @@ int batadv_frag_send_packet(struct sk_bu
+ */
+ if (skb->priority >= 256 && skb->priority <= 263)
+ frag_header.priority = skb->priority - 256;
++ else
++ frag_header.priority = 0;
+
+ ether_addr_copy(frag_header.orig, primary_if->net_dev->dev_addr);
+ ether_addr_copy(frag_header.dest, orig_node->orig);
--- /dev/null
+From foo@baz Tue 17 Mar 2020 11:15:44 AM CET
+From: Sven Eckelmann <sven@narfation.org>
+Date: Mon, 16 Mar 2020 23:31:04 +0100
+Subject: batman-adv: Avoid free/alloc race when handling OGM buffer
+To: stable@vger.kernel.org
+Cc: Sven Eckelmann <sven@narfation.org>, syzbot+0cc629f19ccb8534935b@syzkaller.appspotmail.com, Simon Wunderlich <sw@simonwunderlich.de>
+Message-ID: <20200316223105.6333-24-sven@narfation.org>
+
+From: Sven Eckelmann <sven@narfation.org>
+
+commit 40e220b4218bb3d278e5e8cc04ccdfd1c7ff8307 upstream.
+
+Each slave interface of an B.A.T.M.A.N. IV virtual interface has an OGM
+packet buffer which is initialized using data from netdevice notifier and
+other rtnetlink related hooks. It is sent regularly via various slave
+interfaces of the batadv virtual interface and in this process also
+modified (realloced) to integrate additional state information via TVLV
+containers.
+
+It must be avoided that the worker item is executed without a common lock
+with the netdevice notifier/rtnetlink helpers. Otherwise it can either
+happen that half modified/freed data is sent out or functions modifying the
+OGM buffer try to access already freed memory regions.
+
+Reported-by: syzbot+0cc629f19ccb8534935b@syzkaller.appspotmail.com
+Fixes: c6c8fea29769 ("net: Add batman-adv meshing protocol")
+Signed-off-by: Sven Eckelmann <sven@narfation.org>
+Signed-off-by: Simon Wunderlich <sw@simonwunderlich.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/batman-adv/bat_iv_ogm.c | 60 ++++++++++++++++++++++++++++++++++------
+ net/batman-adv/hard-interface.c | 2 +
+ net/batman-adv/types.h | 2 +
+ 3 files changed, 55 insertions(+), 9 deletions(-)
+
+--- a/net/batman-adv/bat_iv_ogm.c
++++ b/net/batman-adv/bat_iv_ogm.c
+@@ -34,6 +34,7 @@
+ #include <linux/kref.h>
+ #include <linux/list.h>
+ #include <linux/lockdep.h>
++#include <linux/mutex.h>
+ #include <linux/netdevice.h>
+ #include <linux/netlink.h>
+ #include <linux/pkt_sched.h>
+@@ -370,14 +371,18 @@ static int batadv_iv_ogm_iface_enable(st
+ unsigned char *ogm_buff;
+ u32 random_seqno;
+
++ mutex_lock(&hard_iface->bat_iv.ogm_buff_mutex);
++
+ /* randomize initial seqno to avoid collision */
+ get_random_bytes(&random_seqno, sizeof(random_seqno));
+ atomic_set(&hard_iface->bat_iv.ogm_seqno, random_seqno);
+
+ hard_iface->bat_iv.ogm_buff_len = BATADV_OGM_HLEN;
+ ogm_buff = kmalloc(hard_iface->bat_iv.ogm_buff_len, GFP_ATOMIC);
+- if (!ogm_buff)
++ if (!ogm_buff) {
++ mutex_unlock(&hard_iface->bat_iv.ogm_buff_mutex);
+ return -ENOMEM;
++ }
+
+ hard_iface->bat_iv.ogm_buff = ogm_buff;
+
+@@ -389,35 +394,59 @@ static int batadv_iv_ogm_iface_enable(st
+ batadv_ogm_packet->reserved = 0;
+ batadv_ogm_packet->tq = BATADV_TQ_MAX_VALUE;
+
++ mutex_unlock(&hard_iface->bat_iv.ogm_buff_mutex);
++
+ return 0;
+ }
+
+ static void batadv_iv_ogm_iface_disable(struct batadv_hard_iface *hard_iface)
+ {
++ mutex_lock(&hard_iface->bat_iv.ogm_buff_mutex);
++
+ kfree(hard_iface->bat_iv.ogm_buff);
+ hard_iface->bat_iv.ogm_buff = NULL;
++
++ mutex_unlock(&hard_iface->bat_iv.ogm_buff_mutex);
+ }
+
+ static void batadv_iv_ogm_iface_update_mac(struct batadv_hard_iface *hard_iface)
+ {
+ struct batadv_ogm_packet *batadv_ogm_packet;
+- unsigned char *ogm_buff = hard_iface->bat_iv.ogm_buff;
++ void *ogm_buff;
+
+- batadv_ogm_packet = (struct batadv_ogm_packet *)ogm_buff;
++ mutex_lock(&hard_iface->bat_iv.ogm_buff_mutex);
++
++ ogm_buff = hard_iface->bat_iv.ogm_buff;
++ if (!ogm_buff)
++ goto unlock;
++
++ batadv_ogm_packet = ogm_buff;
+ ether_addr_copy(batadv_ogm_packet->orig,
+ hard_iface->net_dev->dev_addr);
+ ether_addr_copy(batadv_ogm_packet->prev_sender,
+ hard_iface->net_dev->dev_addr);
++
++unlock:
++ mutex_unlock(&hard_iface->bat_iv.ogm_buff_mutex);
+ }
+
+ static void
+ batadv_iv_ogm_primary_iface_set(struct batadv_hard_iface *hard_iface)
+ {
+ struct batadv_ogm_packet *batadv_ogm_packet;
+- unsigned char *ogm_buff = hard_iface->bat_iv.ogm_buff;
++ void *ogm_buff;
+
+- batadv_ogm_packet = (struct batadv_ogm_packet *)ogm_buff;
++ mutex_lock(&hard_iface->bat_iv.ogm_buff_mutex);
++
++ ogm_buff = hard_iface->bat_iv.ogm_buff;
++ if (!ogm_buff)
++ goto unlock;
++
++ batadv_ogm_packet = ogm_buff;
+ batadv_ogm_packet->ttl = BATADV_TTL;
++
++unlock:
++ mutex_unlock(&hard_iface->bat_iv.ogm_buff_mutex);
+ }
+
+ /* when do we schedule our own ogm to be sent */
+@@ -923,7 +952,11 @@ batadv_iv_ogm_slide_own_bcast_window(str
+ }
+ }
+
+-static void batadv_iv_ogm_schedule(struct batadv_hard_iface *hard_iface)
++/**
++ * batadv_iv_ogm_schedule_buff() - schedule submission of hardif ogm buffer
++ * @hard_iface: interface whose ogm buffer should be transmitted
++ */
++static void batadv_iv_ogm_schedule_buff(struct batadv_hard_iface *hard_iface)
+ {
+ struct batadv_priv *bat_priv = netdev_priv(hard_iface->soft_iface);
+ unsigned char **ogm_buff = &hard_iface->bat_iv.ogm_buff;
+@@ -934,9 +967,7 @@ static void batadv_iv_ogm_schedule(struc
+ u16 tvlv_len = 0;
+ unsigned long send_time;
+
+- if ((hard_iface->if_status == BATADV_IF_NOT_IN_USE) ||
+- (hard_iface->if_status == BATADV_IF_TO_BE_REMOVED))
+- return;
++ lockdep_assert_held(&hard_iface->bat_iv.ogm_buff_mutex);
+
+ /* the interface gets activated here to avoid race conditions between
+ * the moment of activating the interface in
+@@ -1004,6 +1035,17 @@ out:
+ batadv_hardif_put(primary_if);
+ }
+
++static void batadv_iv_ogm_schedule(struct batadv_hard_iface *hard_iface)
++{
++ if (hard_iface->if_status == BATADV_IF_NOT_IN_USE ||
++ hard_iface->if_status == BATADV_IF_TO_BE_REMOVED)
++ return;
++
++ mutex_lock(&hard_iface->bat_iv.ogm_buff_mutex);
++ batadv_iv_ogm_schedule_buff(hard_iface);
++ mutex_unlock(&hard_iface->bat_iv.ogm_buff_mutex);
++}
++
+ /**
+ * batadv_iv_ogm_orig_update - use OGM to update corresponding data in an
+ * originator
+--- a/net/batman-adv/hard-interface.c
++++ b/net/batman-adv/hard-interface.c
+@@ -28,6 +28,7 @@
+ #include <linux/kernel.h>
+ #include <linux/kref.h>
+ #include <linux/list.h>
++#include <linux/mutex.h>
+ #include <linux/netdevice.h>
+ #include <linux/printk.h>
+ #include <linux/rculist.h>
+@@ -702,6 +703,7 @@ batadv_hardif_add_interface(struct net_d
+ INIT_LIST_HEAD(&hard_iface->list);
+ INIT_HLIST_HEAD(&hard_iface->neigh_list);
+
++ mutex_init(&hard_iface->bat_iv.ogm_buff_mutex);
+ spin_lock_init(&hard_iface->neigh_list_lock);
+ kref_init(&hard_iface->refcount);
+
+--- a/net/batman-adv/types.h
++++ b/net/batman-adv/types.h
+@@ -82,11 +82,13 @@ enum batadv_dhcp_recipient {
+ * @ogm_buff: buffer holding the OGM packet
+ * @ogm_buff_len: length of the OGM packet buffer
+ * @ogm_seqno: OGM sequence number - used to identify each OGM
++ * @ogm_buff_mutex: lock protecting ogm_buff and ogm_buff_len
+ */
+ struct batadv_hard_iface_bat_iv {
+ unsigned char *ogm_buff;
+ int ogm_buff_len;
+ atomic_t ogm_seqno;
++ struct mutex ogm_buff_mutex;
+ };
+
+ /**
--- /dev/null
+From foo@baz Tue 17 Mar 2020 11:15:44 AM CET
+From: Sven Eckelmann <sven@narfation.org>
+Date: Mon, 16 Mar 2020 23:31:03 +0100
+Subject: batman-adv: Avoid free/alloc race when handling OGM2 buffer
+To: stable@vger.kernel.org
+Cc: Sven Eckelmann <sven@narfation.org>, Simon Wunderlich <sw@simonwunderlich.de>
+Message-ID: <20200316223105.6333-23-sven@narfation.org>
+
+From: Sven Eckelmann <sven@narfation.org>
+
+commit a8d23cbbf6c9f515ed678204ad2962be7c336344 upstream.
+
+A B.A.T.M.A.N. V virtual interface has an OGM2 packet buffer which is
+initialized using data from the netdevice notifier and other rtnetlink
+related hooks. It is sent regularly via various slave interfaces of the
+batadv virtual interface and in this process also modified (realloced) to
+integrate additional state information via TVLV containers.
+
+It must be avoided that the worker item is executed without a common lock
+with the netdevice notifier/rtnetlink helpers. Otherwise it can either
+happen that half modified data is sent out or the functions modifying the
+OGM2 buffer try to access already freed memory regions.
+
+Fixes: 0da0035942d4 ("batman-adv: OGMv2 - add basic infrastructure")
+Signed-off-by: Sven Eckelmann <sven@narfation.org>
+Signed-off-by: Simon Wunderlich <sw@simonwunderlich.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/batman-adv/bat_v_ogm.c | 42 ++++++++++++++++++++++++++++++++++--------
+ net/batman-adv/types.h | 3 +++
+ 2 files changed, 37 insertions(+), 8 deletions(-)
+
+--- a/net/batman-adv/bat_v_ogm.c
++++ b/net/batman-adv/bat_v_ogm.c
+@@ -28,6 +28,8 @@
+ #include <linux/kernel.h>
+ #include <linux/kref.h>
+ #include <linux/list.h>
++#include <linux/lockdep.h>
++#include <linux/mutex.h>
+ #include <linux/netdevice.h>
+ #include <linux/random.h>
+ #include <linux/rculist.h>
+@@ -127,22 +129,19 @@ static void batadv_v_ogm_send_to_if(stru
+ }
+
+ /**
+- * batadv_v_ogm_send - periodic worker broadcasting the own OGM
+- * @work: work queue item
++ * batadv_v_ogm_send_softif() - periodic worker broadcasting the own OGM
++ * @bat_priv: the bat priv with all the soft interface information
+ */
+-static void batadv_v_ogm_send(struct work_struct *work)
++static void batadv_v_ogm_send_softif(struct batadv_priv *bat_priv)
+ {
+ struct batadv_hard_iface *hard_iface;
+- struct batadv_priv_bat_v *bat_v;
+- struct batadv_priv *bat_priv;
+ struct batadv_ogm2_packet *ogm_packet;
+ struct sk_buff *skb, *skb_tmp;
+ unsigned char *ogm_buff, *pkt_buff;
+ int ogm_buff_len;
+ u16 tvlv_len = 0;
+
+- bat_v = container_of(work, struct batadv_priv_bat_v, ogm_wq.work);
+- bat_priv = container_of(bat_v, struct batadv_priv, bat_v);
++ lockdep_assert_held(&bat_priv->bat_v.ogm_buff_mutex);
+
+ if (atomic_read(&bat_priv->mesh_state) == BATADV_MESH_DEACTIVATING)
+ goto out;
+@@ -210,6 +209,23 @@ out:
+ }
+
+ /**
++ * batadv_v_ogm_send() - periodic worker broadcasting the own OGM
++ * @work: work queue item
++ */
++static void batadv_v_ogm_send(struct work_struct *work)
++{
++ struct batadv_priv_bat_v *bat_v;
++ struct batadv_priv *bat_priv;
++
++ bat_v = container_of(work, struct batadv_priv_bat_v, ogm_wq.work);
++ bat_priv = container_of(bat_v, struct batadv_priv, bat_v);
++
++ mutex_lock(&bat_priv->bat_v.ogm_buff_mutex);
++ batadv_v_ogm_send_softif(bat_priv);
++ mutex_unlock(&bat_priv->bat_v.ogm_buff_mutex);
++}
++
++/**
+ * batadv_v_ogm_iface_enable - prepare an interface for B.A.T.M.A.N. V
+ * @hard_iface: the interface to prepare
+ *
+@@ -235,11 +251,15 @@ void batadv_v_ogm_primary_iface_set(stru
+ struct batadv_priv *bat_priv = netdev_priv(primary_iface->soft_iface);
+ struct batadv_ogm2_packet *ogm_packet;
+
++ mutex_lock(&bat_priv->bat_v.ogm_buff_mutex);
+ if (!bat_priv->bat_v.ogm_buff)
+- return;
++ goto unlock;
+
+ ogm_packet = (struct batadv_ogm2_packet *)bat_priv->bat_v.ogm_buff;
+ ether_addr_copy(ogm_packet->orig, primary_iface->net_dev->dev_addr);
++
++unlock:
++ mutex_unlock(&bat_priv->bat_v.ogm_buff_mutex);
+ }
+
+ /**
+@@ -827,6 +847,8 @@ int batadv_v_ogm_init(struct batadv_priv
+ atomic_set(&bat_priv->bat_v.ogm_seqno, random_seqno);
+ INIT_DELAYED_WORK(&bat_priv->bat_v.ogm_wq, batadv_v_ogm_send);
+
++ mutex_init(&bat_priv->bat_v.ogm_buff_mutex);
++
+ return 0;
+ }
+
+@@ -838,7 +860,11 @@ void batadv_v_ogm_free(struct batadv_pri
+ {
+ cancel_delayed_work_sync(&bat_priv->bat_v.ogm_wq);
+
++ mutex_lock(&bat_priv->bat_v.ogm_buff_mutex);
++
+ kfree(bat_priv->bat_v.ogm_buff);
+ bat_priv->bat_v.ogm_buff = NULL;
+ bat_priv->bat_v.ogm_buff_len = 0;
++
++ mutex_unlock(&bat_priv->bat_v.ogm_buff_mutex);
+ }
+--- a/net/batman-adv/types.h
++++ b/net/batman-adv/types.h
+@@ -27,6 +27,7 @@
+ #include <linux/compiler.h>
+ #include <linux/if_ether.h>
+ #include <linux/kref.h>
++#include <linux/mutex.h>
+ #include <linux/netdevice.h>
+ #include <linux/netlink.h>
+ #include <linux/sched.h> /* for linux/wait.h */
+@@ -966,12 +967,14 @@ struct batadv_softif_vlan {
+ * @ogm_buff: buffer holding the OGM packet
+ * @ogm_buff_len: length of the OGM packet buffer
+ * @ogm_seqno: OGM sequence number - used to identify each OGM
++ * @ogm_buff_mutex: lock protecting ogm_buff and ogm_buff_len
+ * @ogm_wq: workqueue used to schedule OGM transmissions
+ */
+ struct batadv_priv_bat_v {
+ unsigned char *ogm_buff;
+ int ogm_buff_len;
+ atomic_t ogm_seqno;
++ struct mutex ogm_buff_mutex;
+ struct delayed_work ogm_wq;
+ };
+
--- /dev/null
+From foo@baz Tue 17 Mar 2020 11:15:43 AM CET
+From: Sven Eckelmann <sven@narfation.org>
+Date: Mon, 16 Mar 2020 23:30:54 +0100
+Subject: batman-adv: Avoid race in TT TVLV allocator helper
+To: stable@vger.kernel.org
+Cc: Sven Eckelmann <sven@narfation.org>, Antonio Quartulli <a@unstable.cc>, Simon Wunderlich <sw@simonwunderlich.de>
+Message-ID: <20200316223105.6333-14-sven@narfation.org>
+
+From: Sven Eckelmann <sven@narfation.org>
+
+commit 8ba0f9bd3bdea1058c2b2676bec7905724418e40 upstream.
+
+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: 7ea7b4a14275 ("batman-adv: make the TT CRC logic VLAN specific")
+Signed-off-by: Sven Eckelmann <sven@narfation.org>
+Acked-by: Antonio Quartulli <a@unstable.cc>
+Signed-off-by: Simon Wunderlich <sw@simonwunderlich.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/batman-adv/translation-table.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+--- a/net/batman-adv/translation-table.c
++++ b/net/batman-adv/translation-table.c
+@@ -867,7 +867,7 @@ batadv_tt_prepare_tvlv_global_data(struc
+ 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);
+@@ -905,7 +905,7 @@ batadv_tt_prepare_tvlv_global_data(struc
+ *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;
+ }
+
+@@ -941,7 +941,7 @@ batadv_tt_prepare_tvlv_local_data(struct
+ 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);
+@@ -979,7 +979,7 @@ batadv_tt_prepare_tvlv_local_data(struct
+ *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;
+ }
+
--- /dev/null
+From foo@baz Tue 17 Mar 2020 11:15:43 AM CET
+From: Sven Eckelmann <sven@narfation.org>
+Date: Mon, 16 Mar 2020 23:30:49 +0100
+Subject: batman-adv: Avoid spurious warnings from bat_v neigh_cmp implementation
+To: stable@vger.kernel.org
+Cc: Sven Eckelmann <sven.eckelmann@openmesh.com>, Simon Wunderlich <sw@simonwunderlich.de>
+Message-ID: <20200316223105.6333-9-sven@narfation.org>
+
+From: Sven Eckelmann <sven.eckelmann@openmesh.com>
+
+commit 6a4bc44b012cbc29c9d824be2c7ab9eac8ee6b6f upstream.
+
+The neighbor compare API implementation for B.A.T.M.A.N. V checks whether
+the neigh_ifinfo for this neighbor on a specific interface exists. A
+warning is printed when it isn't found.
+
+But it is not called inside a lock which would prevent that this
+information is lost right before batadv_neigh_ifinfo_get. It must therefore
+be expected that batadv_v_neigh_(cmp|is_sob) might not be able to get the
+requested neigh_ifinfo.
+
+A WARN_ON for such a situation seems not to be appropriate because this
+will only flood the kernel logs. The warnings must therefore be removed.
+
+Signed-off-by: Sven Eckelmann <sven.eckelmann@openmesh.com>
+Signed-off-by: Simon Wunderlich <sw@simonwunderlich.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/batman-adv/bat_v.c | 9 ++++-----
+ 1 file changed, 4 insertions(+), 5 deletions(-)
+
+--- a/net/batman-adv/bat_v.c
++++ b/net/batman-adv/bat_v.c
+@@ -19,7 +19,6 @@
+ #include "main.h"
+
+ #include <linux/atomic.h>
+-#include <linux/bug.h>
+ #include <linux/cache.h>
+ #include <linux/errno.h>
+ #include <linux/if_ether.h>
+@@ -623,11 +622,11 @@ static int batadv_v_neigh_cmp(struct bat
+ int ret = 0;
+
+ ifinfo1 = batadv_neigh_ifinfo_get(neigh1, if_outgoing1);
+- if (WARN_ON(!ifinfo1))
++ if (!ifinfo1)
+ goto err_ifinfo1;
+
+ ifinfo2 = batadv_neigh_ifinfo_get(neigh2, if_outgoing2);
+- if (WARN_ON(!ifinfo2))
++ if (!ifinfo2)
+ goto err_ifinfo2;
+
+ ret = ifinfo1->bat_v.throughput - ifinfo2->bat_v.throughput;
+@@ -649,11 +648,11 @@ static bool batadv_v_neigh_is_sob(struct
+ bool ret = false;
+
+ ifinfo1 = batadv_neigh_ifinfo_get(neigh1, if_outgoing1);
+- if (WARN_ON(!ifinfo1))
++ if (!ifinfo1)
+ goto err_ifinfo1;
+
+ ifinfo2 = batadv_neigh_ifinfo_get(neigh2, if_outgoing2);
+- if (WARN_ON(!ifinfo2))
++ if (!ifinfo2)
+ goto err_ifinfo2;
+
+ threshold = ifinfo1->bat_v.throughput / 4;
--- /dev/null
+From foo@baz Tue 17 Mar 2020 11:15:43 AM CET
+From: Sven Eckelmann <sven@narfation.org>
+Date: Mon, 16 Mar 2020 23:30:59 +0100
+Subject: batman-adv: Avoid storing non-TT-sync flags on singular entries too
+To: stable@vger.kernel.org
+Cc: "Linus Lüssing" <linus.luessing@c0d3.blue>, "Sven Eckelmann" <sven@narfation.org>, "Simon Wunderlich" <sw@simonwunderlich.de>
+Message-ID: <20200316223105.6333-19-sven@narfation.org>
+
+From: Linus Lüssing <linus.luessing@c0d3.blue>
+
+commit 4a519b83da16927fb98fd32b0f598e639d1f1859 upstream.
+
+Since commit 54e22f265e87 ("batman-adv: fix TT sync flag inconsistencies")
+TT sync flags and TT non-sync'd flags are supposed to be stored
+separately.
+
+The previous patch missed to apply this separation on a TT entry with
+only a single TT orig entry.
+
+This is a minor fix because with only a single TT orig entry the DDoS
+issue the former patch solves does not apply.
+
+Fixes: 54e22f265e87 ("batman-adv: fix TT sync flag inconsistencies")
+Signed-off-by: Linus Lüssing <linus.luessing@c0d3.blue>
+Signed-off-by: Sven Eckelmann <sven@narfation.org>
+Signed-off-by: Simon Wunderlich <sw@simonwunderlich.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/batman-adv/translation-table.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/net/batman-adv/translation-table.c
++++ b/net/batman-adv/translation-table.c
+@@ -1708,7 +1708,8 @@ static bool batadv_tt_global_add(struct
+ ether_addr_copy(common->addr, tt_addr);
+ common->vid = vid;
+
+- common->flags = flags;
++ common->flags = flags & (~BATADV_TT_SYNC_MASK);
++
+ tt_global_entry->roam_at = 0;
+ /* node must store current time in case of roaming. This is
+ * needed to purge this entry out on timeout (if nobody claims
--- /dev/null
+From foo@baz Tue 17 Mar 2020 11:15:44 AM CET
+From: Sven Eckelmann <sven@narfation.org>
+Date: Mon, 16 Mar 2020 23:31:05 +0100
+Subject: batman-adv: Don't schedule OGM for disabled interface
+To: stable@vger.kernel.org
+Cc: Sven Eckelmann <sven@narfation.org>, syzbot+a98f2016f40b9cd3818a@syzkaller.appspotmail.com, syzbot+ac36b6a33c28a491e929@syzkaller.appspotmail.com, Hillf Danton <hdanton@sina.com>, Simon Wunderlich <sw@simonwunderlich.de>
+Message-ID: <20200316223105.6333-25-sven@narfation.org>
+
+From: Sven Eckelmann <sven@narfation.org>
+
+A transmission scheduling for an interface which is currently dropped by
+batadv_iv_ogm_iface_disable could still be in progress. The B.A.T.M.A.N. V
+is simply cancelling the workqueue item in an synchronous way but this is
+not possible with B.A.T.M.A.N. IV because the OGM submissions are
+intertwined.
+
+Instead it has to stop submitting the OGM when it detect that the buffer
+pointer is set to NULL.
+
+Reported-by: syzbot+a98f2016f40b9cd3818a@syzkaller.appspotmail.com
+Reported-by: syzbot+ac36b6a33c28a491e929@syzkaller.appspotmail.com
+Fixes: c6c8fea29769 ("net: Add batman-adv meshing protocol")
+Signed-off-by: Sven Eckelmann <sven@narfation.org>
+Cc: Hillf Danton <hdanton@sina.com>
+Signed-off-by: Simon Wunderlich <sw@simonwunderlich.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/batman-adv/bat_iv_ogm.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/net/batman-adv/bat_iv_ogm.c
++++ b/net/batman-adv/bat_iv_ogm.c
+@@ -969,6 +969,10 @@ static void batadv_iv_ogm_schedule_buff(
+
+ lockdep_assert_held(&hard_iface->bat_iv.ogm_buff_mutex);
+
++ /* interface already disabled by batadv_iv_ogm_iface_disable */
++ if (!*ogm_buff)
++ return;
++
+ /* the interface gets activated here to avoid race conditions between
+ * the moment of activating the interface in
+ * hardif_activate_interface() where the originator mac is set and
--- /dev/null
+From foo@baz Tue 17 Mar 2020 11:15:43 AM CET
+From: Sven Eckelmann <sven@narfation.org>
+Date: Mon, 16 Mar 2020 23:30:51 +0100
+Subject: batman-adv: Fix check of retrieved orig_gw in batadv_v_gw_is_eligible
+To: stable@vger.kernel.org
+Cc: Sven Eckelmann <sven.eckelmann@openmesh.com>, Antonio Quartulli <a@unstable.cc>, Simon Wunderlich <sw@simonwunderlich.de>
+Message-ID: <20200316223105.6333-11-sven@narfation.org>
+
+From: Sven Eckelmann <sven.eckelmann@openmesh.com>
+
+commit 198a62ddffa4a4ffaeb741f642b7b52f2d91ae9b upstream.
+
+The batadv_v_gw_is_eligible function already assumes that orig_node is not
+NULL. But batadv_gw_node_get may have failed to find the originator. It
+must therefore be checked whether the batadv_gw_node_get failed and not
+whether orig_node is NULL to detect this error.
+
+Fixes: 50164d8f500f ("batman-adv: B.A.T.M.A.N. V - implement GW selection logic")
+Signed-off-by: Sven Eckelmann <sven.eckelmann@openmesh.com>
+Acked-by: Antonio Quartulli <a@unstable.cc>
+Signed-off-by: Simon Wunderlich <sw@simonwunderlich.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/batman-adv/bat_v.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/net/batman-adv/bat_v.c
++++ b/net/batman-adv/bat_v.c
+@@ -814,7 +814,7 @@ static bool batadv_v_gw_is_eligible(stru
+ }
+
+ orig_gw = batadv_gw_node_get(bat_priv, orig_node);
+- if (!orig_node)
++ if (!orig_gw)
+ goto out;
+
+ if (batadv_v_gw_throughput_get(orig_gw, &orig_throughput) < 0)
--- /dev/null
+From foo@baz Tue 17 Mar 2020 11:15:43 AM CET
+From: Sven Eckelmann <sven@narfation.org>
+Date: Mon, 16 Mar 2020 23:30:57 +0100
+Subject: batman-adv: Fix debugfs path for renamed hardif
+To: stable@vger.kernel.org
+Cc: Sven Eckelmann <sven@narfation.org>, John Soros <sorosj@gmail.com>, Simon Wunderlich <sw@simonwunderlich.de>
+Message-ID: <20200316223105.6333-17-sven@narfation.org>
+
+From: Sven Eckelmann <sven@narfation.org>
+
+commit 36dc621ceca1be3ec885aeade5fdafbbcc452a6d upstream.
+
+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: 5bc7c1eb44f2 ("batman-adv: add debugfs structure for information per interface")
+Reported-by: John Soros <sorosj@gmail.com>
+Signed-off-by: Sven Eckelmann <sven@narfation.org>
+Signed-off-by: Simon Wunderlich <sw@simonwunderlich.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/batman-adv/debugfs.c | 20 ++++++++++++++++++++
+ net/batman-adv/debugfs.h | 6 ++++++
+ net/batman-adv/hard-interface.c | 3 +++
+ 3 files changed, 29 insertions(+)
+
+--- 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>
+@@ -340,6 +341,25 @@ out:
+ }
+
+ /**
++ * 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.
+ * @hard_iface: hard interface which is deleted.
+--- 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
+@@ -59,6 +60,11 @@ int batadv_debugfs_add_hardif(struct bat
+ }
+
+ 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)
+ {
+ }
+--- a/net/batman-adv/hard-interface.c
++++ b/net/batman-adv/hard-interface.c
+@@ -812,6 +812,9 @@ static int batadv_hard_if_event(struct n
+ if (hard_iface == primary_if)
+ batadv_primary_if_update_addr(bat_priv, NULL);
+ break;
++ case NETDEV_CHANGENAME:
++ batadv_debugfs_rename_hardif(hard_iface);
++ break;
+ default:
+ break;
+ }
--- /dev/null
+From foo@baz Tue 17 Mar 2020 11:15:43 AM CET
+From: Sven Eckelmann <sven@narfation.org>
+Date: Mon, 16 Mar 2020 23:30:58 +0100
+Subject: batman-adv: Fix debugfs path for renamed softif
+To: stable@vger.kernel.org
+Cc: Sven Eckelmann <sven@narfation.org>, Simon Wunderlich <sw@simonwunderlich.de>
+Message-ID: <20200316223105.6333-18-sven@narfation.org>
+
+From: Sven Eckelmann <sven@narfation.org>
+
+commit 6da7be7d24b2921f8215473ba7552796dff05fe1 upstream.
+
+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: c6c8fea29769 ("net: Add batman-adv meshing protocol")
+Signed-off-by: Sven Eckelmann <sven@narfation.org>
+Signed-off-by: Simon Wunderlich <sw@simonwunderlich.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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(-)
+
+--- a/net/batman-adv/debugfs.c
++++ b/net/batman-adv/debugfs.c
+@@ -423,6 +423,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);
+--- 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_mes
+ return 0;
+ }
+
++static inline void batadv_debugfs_rename_meshif(struct net_device *dev)
++{
++}
++
+ static inline void batadv_debugfs_del_meshif(struct net_device *dev)
+ {
+ }
+--- a/net/batman-adv/hard-interface.c
++++ b/net/batman-adv/hard-interface.c
+@@ -755,6 +755,32 @@ void batadv_hardif_remove_interfaces(voi
+ 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)
+ {
+@@ -763,12 +789,8 @@ static int batadv_hard_if_event(struct n
+ 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 ||
--- /dev/null
+From foo@baz Tue 17 Mar 2020 11:15:43 AM CET
+From: Sven Eckelmann <sven@narfation.org>
+Date: Mon, 16 Mar 2020 23:30:42 +0100
+Subject: batman-adv: Fix double free during fragment merge error
+To: stable@vger.kernel.org
+Cc: Sven Eckelmann <sven@narfation.org>, Simon Wunderlich <sw@simonwunderlich.de>
+Message-ID: <20200316223105.6333-2-sven@narfation.org>
+
+From: Sven Eckelmann <sven@narfation.org>
+
+commit 248e23b50e2da0753f3b5faa068939cbe9f8a75a upstream.
+
+The function batadv_frag_skb_buffer was supposed not to consume the skbuff
+on errors. This was followed in the helper function
+batadv_frag_insert_packet when the skb would potentially be inserted in the
+fragment queue. But it could happen that the next helper function
+batadv_frag_merge_packets would try to merge the fragments and fail. This
+results in a kfree_skb of all the enqueued fragments (including the just
+inserted one). batadv_recv_frag_packet would detect the error in
+batadv_frag_skb_buffer and try to free the skb again.
+
+The behavior of batadv_frag_skb_buffer (and its helper
+batadv_frag_insert_packet) must therefore be changed to always consume the
+skbuff to have a common behavior and avoid the double kfree_skb.
+
+Fixes: 610bfc6bc99b ("batman-adv: Receive fragmented packets and merge")
+Signed-off-by: Sven Eckelmann <sven@narfation.org>
+Signed-off-by: Simon Wunderlich <sw@simonwunderlich.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/batman-adv/fragmentation.c | 8 +++++---
+ net/batman-adv/routing.c | 6 ++++++
+ 2 files changed, 11 insertions(+), 3 deletions(-)
+
+--- a/net/batman-adv/fragmentation.c
++++ b/net/batman-adv/fragmentation.c
+@@ -232,8 +232,10 @@ err_unlock:
+ spin_unlock_bh(&chain->lock);
+
+ err:
+- if (!ret)
++ if (!ret) {
+ kfree(frag_entry_new);
++ kfree_skb(skb);
++ }
+
+ return ret;
+ }
+@@ -305,7 +307,7 @@ free:
+ *
+ * There are three possible outcomes: 1) Packet is merged: Return true and
+ * set *skb to merged packet; 2) Packet is buffered: Return true and set *skb
+- * to NULL; 3) Error: Return false and leave skb as is.
++ * to NULL; 3) Error: Return false and free skb.
+ *
+ * Return: true when packet is merged or buffered, false when skb is not not
+ * used.
+@@ -330,9 +332,9 @@ bool batadv_frag_skb_buffer(struct sk_bu
+ goto out_err;
+
+ out:
+- *skb = skb_out;
+ ret = true;
+ out_err:
++ *skb = skb_out;
+ return ret;
+ }
+
+--- a/net/batman-adv/routing.c
++++ b/net/batman-adv/routing.c
+@@ -1080,6 +1080,12 @@ int batadv_recv_frag_packet(struct sk_bu
+ batadv_inc_counter(bat_priv, BATADV_CNT_FRAG_RX);
+ batadv_add_counter(bat_priv, BATADV_CNT_FRAG_RX_BYTES, skb->len);
+
++ /* batadv_frag_skb_buffer will always consume the skb and
++ * the caller should therefore never try to free the
++ * skb after this point
++ */
++ ret = NET_RX_SUCCESS;
++
+ /* Add fragment to buffer and merge if possible. */
+ if (!batadv_frag_skb_buffer(&skb, orig_node_src))
+ goto out;
--- /dev/null
+From foo@baz Tue 17 Mar 2020 11:15:44 AM CET
+From: Sven Eckelmann <sven@narfation.org>
+Date: Mon, 16 Mar 2020 23:31:02 +0100
+Subject: batman-adv: Fix duplicated OGMs on NETDEV_UP
+To: stable@vger.kernel.org
+Cc: "Sven Eckelmann" <sven@narfation.org>, "Linus Lüssing" <linus.luessing@c0d3.blue>, "Marek Lindner" <mareklindner@neomailbox.ch>, "Simon Wunderlich" <sw@simonwunderlich.de>
+Message-ID: <20200316223105.6333-22-sven@narfation.org>
+
+From: Sven Eckelmann <sven@narfation.org>
+
+commit 9e6b5648bbc4cd48fab62cecbb81e9cc3c6e7e88 upstream.
+
+The state of slave interfaces are handled differently depending on whether
+the interface is up or not. All active interfaces (IFF_UP) will transmit
+OGMs. But for B.A.T.M.A.N. IV, also non-active interfaces are scheduling
+(low TTL) OGMs on active interfaces. The code which setups and schedules
+the OGMs must therefore already be called when the interfaces gets added as
+slave interface and the transmit function must then check whether it has to
+send out the OGM or not on the specific slave interface.
+
+But the commit f0d97253fb5f ("batman-adv: remove ogm_emit and ogm_schedule
+API calls") moved the setup code from the enable function to the activate
+function. The latter is called either when the added slave was already up
+when batadv_hardif_enable_interface processed the new interface or when a
+NETDEV_UP event was received for this slave interfac. As result, each
+NETDEV_UP would schedule a new OGM worker for the interface and thus OGMs
+would be send a lot more than expected.
+
+Fixes: f0d97253fb5f ("batman-adv: remove ogm_emit and ogm_schedule API calls")
+Reported-by: Linus Lüssing <linus.luessing@c0d3.blue>
+Tested-by: Linus Lüssing <linus.luessing@c0d3.blue>
+Acked-by: Marek Lindner <mareklindner@neomailbox.ch>
+Signed-off-by: Sven Eckelmann <sven@narfation.org>
+Signed-off-by: Simon Wunderlich <sw@simonwunderlich.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/batman-adv/bat_iv_ogm.c | 4 ++--
+ net/batman-adv/hard-interface.c | 3 +++
+ net/batman-adv/types.h | 2 ++
+ 3 files changed, 7 insertions(+), 2 deletions(-)
+
+--- a/net/batman-adv/bat_iv_ogm.c
++++ b/net/batman-adv/bat_iv_ogm.c
+@@ -2477,7 +2477,7 @@ batadv_iv_ogm_neigh_is_sob(struct batadv
+ return ret;
+ }
+
+-static void batadv_iv_iface_activate(struct batadv_hard_iface *hard_iface)
++static void batadv_iv_iface_enabled(struct batadv_hard_iface *hard_iface)
+ {
+ /* begin scheduling originator messages on that interface */
+ batadv_iv_ogm_schedule(hard_iface);
+@@ -2817,8 +2817,8 @@ unlock:
+ static struct batadv_algo_ops batadv_batman_iv __read_mostly = {
+ .name = "BATMAN_IV",
+ .iface = {
+- .activate = batadv_iv_iface_activate,
+ .enable = batadv_iv_ogm_iface_enable,
++ .enabled = batadv_iv_iface_enabled,
+ .disable = batadv_iv_ogm_iface_disable,
+ .update_mac = batadv_iv_ogm_iface_update_mac,
+ .primary_set = batadv_iv_ogm_primary_iface_set,
+--- a/net/batman-adv/hard-interface.c
++++ b/net/batman-adv/hard-interface.c
+@@ -596,6 +596,9 @@ int batadv_hardif_enable_interface(struc
+
+ batadv_hardif_recalc_extra_skbroom(soft_iface);
+
++ if (bat_priv->algo_ops->iface.enabled)
++ bat_priv->algo_ops->iface.enabled(hard_iface);
++
+ out:
+ return 0;
+
+--- a/net/batman-adv/types.h
++++ b/net/batman-adv/types.h
+@@ -1399,6 +1399,7 @@ struct batadv_forw_packet {
+ * @activate: start routing mechanisms when hard-interface is brought up
+ * (optional)
+ * @enable: init routing info when hard-interface is enabled
++ * @enabled: notification when hard-interface was enabled (optional)
+ * @disable: de-init routing info when hard-interface is disabled
+ * @update_mac: (re-)init mac addresses of the protocol information
+ * belonging to this hard-interface
+@@ -1407,6 +1408,7 @@ struct batadv_forw_packet {
+ struct batadv_algo_iface_ops {
+ void (*activate)(struct batadv_hard_iface *hard_iface);
+ int (*enable)(struct batadv_hard_iface *hard_iface);
++ void (*enabled)(struct batadv_hard_iface *hard_iface);
+ void (*disable)(struct batadv_hard_iface *hard_iface);
+ void (*update_mac)(struct batadv_hard_iface *hard_iface);
+ void (*primary_set)(struct batadv_hard_iface *hard_iface);
--- /dev/null
+From foo@baz Tue 17 Mar 2020 11:15:43 AM CET
+From: Sven Eckelmann <sven@narfation.org>
+Date: Mon, 16 Mar 2020 23:30:53 +0100
+Subject: batman-adv: Fix internal interface indices types
+To: stable@vger.kernel.org
+Cc: Sven Eckelmann <sven@narfation.org>, Simon Wunderlich <sw@simonwunderlich.de>
+Message-ID: <20200316223105.6333-13-sven@narfation.org>
+
+From: Sven Eckelmann <sven@narfation.org>
+
+commit f22e08932c2960f29b5e828e745c9f3fb7c1bb86 upstream.
+
+batman-adv uses internal indices for each enabled and active interface.
+It is currently used by the B.A.T.M.A.N. IV algorithm to identifify the
+correct position in the ogm_cnt bitmaps.
+
+The type for the number of enabled interfaces (which defines the next
+interface index) was set to char. This type can be (depending on the
+architecture) either signed (limiting batman-adv to 127 active slave
+interfaces) or unsigned (limiting batman-adv to 255 active slave
+interfaces).
+
+This limit was not correctly checked when an interface was enabled and thus
+an overflow happened. This was only catched on systems with the signed char
+type when the B.A.T.M.A.N. IV code tried to resize its counter arrays with
+a negative size.
+
+The if_num interface index was only a s16 and therefore significantly
+smaller than the ifindex (int) used by the code net code.
+
+Both &batadv_hard_iface->if_num and &batadv_priv->num_ifaces must be
+(unsigned) int to support the same number of slave interfaces as the net
+core code. And the interface activation code must check the number of
+active slave interfaces to avoid integer overflows.
+
+Fixes: c6c8fea29769 ("net: Add batman-adv meshing protocol")
+Signed-off-by: Sven Eckelmann <sven@narfation.org>
+Signed-off-by: Simon Wunderlich <sw@simonwunderlich.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/batman-adv/bat_iv_ogm.c | 24 ++++++++++++++----------
+ net/batman-adv/hard-interface.c | 9 +++++++--
+ net/batman-adv/originator.c | 4 ++--
+ net/batman-adv/originator.h | 4 ++--
+ net/batman-adv/types.h | 11 ++++++-----
+ 5 files changed, 31 insertions(+), 21 deletions(-)
+
+--- a/net/batman-adv/bat_iv_ogm.c
++++ b/net/batman-adv/bat_iv_ogm.c
+@@ -149,7 +149,7 @@ static void batadv_iv_ogm_orig_free(stru
+ * Return: 0 on success, a negative error code otherwise.
+ */
+ static int batadv_iv_ogm_orig_add_if(struct batadv_orig_node *orig_node,
+- int max_if_num)
++ unsigned int max_if_num)
+ {
+ void *data_ptr;
+ size_t old_size;
+@@ -193,7 +193,8 @@ unlock:
+ */
+ static void
+ batadv_iv_ogm_drop_bcast_own_entry(struct batadv_orig_node *orig_node,
+- int max_if_num, int del_if_num)
++ unsigned int max_if_num,
++ unsigned int del_if_num)
+ {
+ size_t chunk_size;
+ size_t if_offset;
+@@ -231,7 +232,8 @@ batadv_iv_ogm_drop_bcast_own_entry(struc
+ */
+ static void
+ batadv_iv_ogm_drop_bcast_own_sum_entry(struct batadv_orig_node *orig_node,
+- int max_if_num, int del_if_num)
++ unsigned int max_if_num,
++ unsigned int del_if_num)
+ {
+ size_t if_offset;
+ void *data_ptr;
+@@ -268,7 +270,8 @@ batadv_iv_ogm_drop_bcast_own_sum_entry(s
+ * Return: 0 on success, a negative error code otherwise.
+ */
+ static int batadv_iv_ogm_orig_del_if(struct batadv_orig_node *orig_node,
+- int max_if_num, int del_if_num)
++ unsigned int max_if_num,
++ unsigned int del_if_num)
+ {
+ spin_lock_bh(&orig_node->bat_iv.ogm_cnt_lock);
+
+@@ -302,7 +305,8 @@ static struct batadv_orig_node *
+ batadv_iv_ogm_orig_get(struct batadv_priv *bat_priv, const u8 *addr)
+ {
+ struct batadv_orig_node *orig_node;
+- int size, hash_added;
++ int hash_added;
++ size_t size;
+
+ orig_node = batadv_orig_hash_find(bat_priv, addr);
+ if (orig_node)
+@@ -898,7 +902,7 @@ batadv_iv_ogm_slide_own_bcast_window(str
+ u32 i;
+ size_t word_index;
+ u8 *w;
+- int if_num;
++ unsigned int if_num;
+
+ for (i = 0; i < hash->size; i++) {
+ head = &hash->table[i];
+@@ -1028,7 +1032,7 @@ batadv_iv_ogm_orig_update(struct batadv_
+ struct batadv_neigh_node *tmp_neigh_node = NULL;
+ struct batadv_neigh_node *router = NULL;
+ struct batadv_orig_node *orig_node_tmp;
+- int if_num;
++ unsigned int if_num;
+ u8 sum_orig, sum_neigh;
+ u8 *neigh_addr;
+ u8 tq_avg;
+@@ -1186,7 +1190,7 @@ static bool batadv_iv_ogm_calc_tq(struct
+ u8 total_count;
+ u8 orig_eq_count, neigh_rq_count, neigh_rq_inv, tq_own;
+ unsigned int neigh_rq_inv_cube, neigh_rq_max_cube;
+- int if_num;
++ unsigned int if_num;
+ unsigned int tq_asym_penalty, inv_asym_penalty;
+ unsigned int combined_tq;
+ unsigned int tq_iface_penalty;
+@@ -1705,9 +1709,9 @@ static void batadv_iv_ogm_process(const
+
+ if (is_my_orig) {
+ unsigned long *word;
+- int offset;
++ size_t offset;
+ s32 bit_pos;
+- s16 if_num;
++ unsigned int if_num;
+ u8 *weight;
+
+ orig_neigh_node = batadv_iv_ogm_orig_get(bat_priv,
+--- a/net/batman-adv/hard-interface.c
++++ b/net/batman-adv/hard-interface.c
+@@ -539,6 +539,11 @@ int batadv_hardif_enable_interface(struc
+ hard_iface->soft_iface = soft_iface;
+ bat_priv = netdev_priv(hard_iface->soft_iface);
+
++ if (bat_priv->num_ifaces >= UINT_MAX) {
++ ret = -ENOSPC;
++ goto err_dev;
++ }
++
+ ret = netdev_master_upper_dev_link(hard_iface->net_dev,
+ soft_iface, NULL, NULL);
+ if (ret)
+@@ -646,7 +651,7 @@ void batadv_hardif_disable_interface(str
+ batadv_hardif_recalc_extra_skbroom(hard_iface->soft_iface);
+
+ /* nobody uses this interface anymore */
+- if (!bat_priv->num_ifaces) {
++ if (bat_priv->num_ifaces == 0) {
+ batadv_gw_check_client_stop(bat_priv);
+
+ if (autodel == BATADV_IF_CLEANUP_AUTO)
+@@ -682,7 +687,7 @@ batadv_hardif_add_interface(struct net_d
+ if (ret)
+ goto free_if;
+
+- hard_iface->if_num = -1;
++ hard_iface->if_num = 0;
+ hard_iface->net_dev = net_dev;
+ hard_iface->soft_iface = NULL;
+ hard_iface->if_status = BATADV_IF_NOT_IN_USE;
+--- a/net/batman-adv/originator.c
++++ b/net/batman-adv/originator.c
+@@ -1495,7 +1495,7 @@ int batadv_orig_dump(struct sk_buff *msg
+ }
+
+ int batadv_orig_hash_add_if(struct batadv_hard_iface *hard_iface,
+- int max_if_num)
++ unsigned int max_if_num)
+ {
+ struct batadv_priv *bat_priv = netdev_priv(hard_iface->soft_iface);
+ struct batadv_algo_ops *bao = bat_priv->algo_ops;
+@@ -1530,7 +1530,7 @@ err:
+ }
+
+ int batadv_orig_hash_del_if(struct batadv_hard_iface *hard_iface,
+- int max_if_num)
++ unsigned int max_if_num)
+ {
+ struct batadv_priv *bat_priv = netdev_priv(hard_iface->soft_iface);
+ struct batadv_hashtable *hash = bat_priv->orig_hash;
+--- a/net/batman-adv/originator.h
++++ b/net/batman-adv/originator.h
+@@ -78,9 +78,9 @@ int batadv_orig_seq_print_text(struct se
+ int batadv_orig_dump(struct sk_buff *msg, struct netlink_callback *cb);
+ int batadv_orig_hardif_seq_print_text(struct seq_file *seq, void *offset);
+ int batadv_orig_hash_add_if(struct batadv_hard_iface *hard_iface,
+- int max_if_num);
++ unsigned int max_if_num);
+ int batadv_orig_hash_del_if(struct batadv_hard_iface *hard_iface,
+- int max_if_num);
++ unsigned int max_if_num);
+ struct batadv_orig_node_vlan *
+ batadv_orig_node_vlan_new(struct batadv_orig_node *orig_node,
+ unsigned short vid);
+--- a/net/batman-adv/types.h
++++ b/net/batman-adv/types.h
+@@ -139,7 +139,7 @@ struct batadv_hard_iface_bat_v {
+ */
+ struct batadv_hard_iface {
+ struct list_head list;
+- s16 if_num;
++ unsigned int if_num;
+ char if_status;
+ struct net_device *net_dev;
+ u8 num_bcasts;
+@@ -1060,7 +1060,7 @@ struct batadv_priv {
+ atomic_t bcast_seqno;
+ atomic_t bcast_queue_left;
+ atomic_t batman_queue_left;
+- char num_ifaces;
++ unsigned int num_ifaces;
+ struct kobject *mesh_obj;
+ struct dentry *debug_dir;
+ struct hlist_head forw_bat_list;
+@@ -1454,9 +1454,10 @@ struct batadv_algo_neigh_ops {
+ */
+ struct batadv_algo_orig_ops {
+ void (*free)(struct batadv_orig_node *orig_node);
+- int (*add_if)(struct batadv_orig_node *orig_node, int max_if_num);
+- int (*del_if)(struct batadv_orig_node *orig_node, int max_if_num,
+- int del_if_num);
++ int (*add_if)(struct batadv_orig_node *orig_node,
++ unsigned int max_if_num);
++ int (*del_if)(struct batadv_orig_node *orig_node,
++ unsigned int max_if_num, unsigned int del_if_num);
+ #ifdef CONFIG_BATMAN_ADV_DEBUGFS
+ void (*print)(struct batadv_priv *priv, struct seq_file *seq,
+ struct batadv_hard_iface *hard_iface);
--- /dev/null
+From foo@baz Tue 17 Mar 2020 11:15:43 AM CET
+From: Sven Eckelmann <sven@narfation.org>
+Date: Mon, 16 Mar 2020 23:30:52 +0100
+Subject: batman-adv: Fix lock for ogm cnt access in batadv_iv_ogm_calc_tq
+To: stable@vger.kernel.org
+Cc: Sven Eckelmann <sven@narfation.org>, Simon Wunderlich <sw@simonwunderlich.de>
+Message-ID: <20200316223105.6333-12-sven@narfation.org>
+
+From: Sven Eckelmann <sven@narfation.org>
+
+commit 5ba7dcfe77037b67016263ea597a8b431692ecab upstream.
+
+The originator node object orig_neigh_node is used to when accessing the
+bcast_own(_sum) and real_packet_count information. The access to them has
+to be protected with the spinlock in orig_neigh_node.
+
+But the function uses the lock in orig_node instead. This is incorrect
+because they could be two different originator node objects.
+
+Fixes: 0ede9f41b217 ("batman-adv: protect bit operations to count OGMs with spinlock")
+Signed-off-by: Sven Eckelmann <sven@narfation.org>
+Signed-off-by: Simon Wunderlich <sw@simonwunderlich.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/batman-adv/bat_iv_ogm.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/net/batman-adv/bat_iv_ogm.c
++++ b/net/batman-adv/bat_iv_ogm.c
+@@ -1227,7 +1227,7 @@ static bool batadv_iv_ogm_calc_tq(struct
+ orig_node->last_seen = jiffies;
+
+ /* find packet count of corresponding one hop neighbor */
+- spin_lock_bh(&orig_node->bat_iv.ogm_cnt_lock);
++ spin_lock_bh(&orig_neigh_node->bat_iv.ogm_cnt_lock);
+ if_num = if_incoming->if_num;
+ orig_eq_count = orig_neigh_node->bat_iv.bcast_own_sum[if_num];
+ neigh_ifinfo = batadv_neigh_ifinfo_new(neigh_node, if_outgoing);
+@@ -1237,7 +1237,7 @@ static bool batadv_iv_ogm_calc_tq(struct
+ } else {
+ neigh_rq_count = 0;
+ }
+- spin_unlock_bh(&orig_node->bat_iv.ogm_cnt_lock);
++ spin_unlock_bh(&orig_neigh_node->bat_iv.ogm_cnt_lock);
+
+ /* pay attention to not get a value bigger than 100 % */
+ if (orig_eq_count > neigh_rq_count)
--- /dev/null
+From foo@baz Tue 17 Mar 2020 11:15:44 AM CET
+From: Sven Eckelmann <sven@narfation.org>
+Date: Mon, 16 Mar 2020 23:31:00 +0100
+Subject: batman-adv: Fix multicast TT issues with bogus ROAM flags
+To: stable@vger.kernel.org
+Cc: "Linus Lüssing" <linus.luessing@c0d3.blue>, "Leonardo Mörlein" <me@irrelefant.net>, "Simon Wunderlich" <sw@simonwunderlich.de>
+Message-ID: <20200316223105.6333-20-sven@narfation.org>
+
+From: Linus Lüssing <linus.luessing@c0d3.blue>
+
+commit a44ebeff6bbd6ef50db41b4195fca87b21aefd20 upstream.
+
+When a (broken) node wrongly sends multicast TT entries with a ROAM
+flag then this causes any receiving node to drop all entries for the
+same multicast MAC address announced by other nodes, leading to
+packet loss.
+
+Fix this DoS vector by only storing TT sync flags. For multicast TT
+non-sync'ing flag bits like ROAM are unused so far anyway.
+
+Fixes: 1d8ab8d3c176 ("batman-adv: Modified forwarding behaviour for multicast packets")
+Reported-by: Leonardo Mörlein <me@irrelefant.net>
+Signed-off-by: Linus Lüssing <linus.luessing@c0d3.blue>
+Signed-off-by: Simon Wunderlich <sw@simonwunderlich.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/batman-adv/translation-table.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+--- a/net/batman-adv/translation-table.c
++++ b/net/batman-adv/translation-table.c
+@@ -1708,7 +1708,8 @@ static bool batadv_tt_global_add(struct
+ ether_addr_copy(common->addr, tt_addr);
+ common->vid = vid;
+
+- common->flags = flags & (~BATADV_TT_SYNC_MASK);
++ if (!is_multicast_ether_addr(common->addr))
++ common->flags = flags & (~BATADV_TT_SYNC_MASK);
+
+ tt_global_entry->roam_at = 0;
+ /* node must store current time in case of roaming. This is
+@@ -1772,7 +1773,8 @@ static bool batadv_tt_global_add(struct
+ * TT_CLIENT_TEMP, therefore they have to be copied in the
+ * client entry
+ */
+- common->flags |= flags & (~BATADV_TT_SYNC_MASK);
++ if (!is_multicast_ether_addr(common->addr))
++ common->flags |= flags & (~BATADV_TT_SYNC_MASK);
+
+ /* If there is the BATADV_TT_CLIENT_ROAM flag set, there is only
+ * one originator left in the list and we previously received a
--- /dev/null
+From foo@baz Tue 17 Mar 2020 11:15:43 AM CET
+From: Sven Eckelmann <sven@narfation.org>
+Date: Mon, 16 Mar 2020 23:30:45 +0100
+Subject: batman-adv: Fix rx packet/bytes stats on local ARP reply
+To: stable@vger.kernel.org
+Cc: Sven Eckelmann <sven@narfation.org>, Simon Wunderlich <sw@simonwunderlich.de>
+Message-ID: <20200316223105.6333-5-sven@narfation.org>
+
+From: Sven Eckelmann <sven@narfation.org>
+
+commit 36d4d68cd658d914ef73ac845705c4a89e7d9e2f upstream.
+
+The stats are generated by batadv_interface_stats and must not be stored
+directly in the net_device stats member variable. The batadv_priv
+bat_counters information is assembled when ndo_get_stats is called. The
+stats previously stored in net_device::stats is then overwritten.
+
+The batman-adv counters must therefore be increased when an ARP packet is
+answered locally via the distributed arp table.
+
+Fixes: c384ea3ec930 ("batman-adv: Distributed ARP Table - add snooping functions for ARP messages")
+Signed-off-by: Sven Eckelmann <sven@narfation.org>
+Signed-off-by: Simon Wunderlich <sw@simonwunderlich.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/batman-adv/distributed-arp-table.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+--- a/net/batman-adv/distributed-arp-table.c
++++ b/net/batman-adv/distributed-arp-table.c
+@@ -1025,8 +1025,9 @@ bool batadv_dat_snoop_outgoing_arp_reque
+ skb_reset_mac_header(skb_new);
+ skb_new->protocol = eth_type_trans(skb_new,
+ bat_priv->soft_iface);
+- bat_priv->stats.rx_packets++;
+- bat_priv->stats.rx_bytes += skb->len + ETH_HLEN + hdr_size;
++ batadv_inc_counter(bat_priv, BATADV_CNT_RX);
++ batadv_add_counter(bat_priv, BATADV_CNT_RX_BYTES,
++ skb->len + ETH_HLEN + hdr_size);
+ bat_priv->soft_iface->last_rx = jiffies;
+
+ netif_rx(skb_new);
--- /dev/null
+From foo@baz Tue 17 Mar 2020 11:15:43 AM CET
+From: Sven Eckelmann <sven@narfation.org>
+Date: Mon, 16 Mar 2020 23:30:43 +0100
+Subject: batman-adv: Fix transmission of final, 16th fragment
+To: stable@vger.kernel.org
+Cc: "Linus Lüssing" <linus.luessing@c0d3.blue>, "Sven Eckelmann" <sven@narfation.org>, "Simon Wunderlich" <sw@simonwunderlich.de>
+Message-ID: <20200316223105.6333-3-sven@narfation.org>
+
+From: Linus Lüssing <linus.luessing@c0d3.blue>
+
+commit 51c6b429c0c95e67edd1cb0b548c5cf6a6604763 upstream.
+
+Trying to split and transmit a unicast packet in 16 parts will fail for
+the final fragment: After having sent the 15th one with a frag_packet.no
+index of 14, we will increase the the index to 15 - and return with an
+error code immediately, even though one more fragment is due for
+transmission and allowed.
+
+Fixing this issue by moving the check before incrementing the index.
+
+While at it, adding an unlikely(), because the check is actually more of
+an assertion.
+
+Fixes: ee75ed88879a ("batman-adv: Fragment and send skbs larger than mtu")
+Signed-off-by: Linus Lüssing <linus.luessing@c0d3.blue>
+Signed-off-by: Sven Eckelmann <sven@narfation.org>
+Signed-off-by: Simon Wunderlich <sw@simonwunderlich.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/batman-adv/fragmentation.c | 12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+--- a/net/batman-adv/fragmentation.c
++++ b/net/batman-adv/fragmentation.c
+@@ -490,6 +490,12 @@ int batadv_frag_send_packet(struct sk_bu
+
+ /* Eat and send fragments from the tail of skb */
+ while (skb->len > max_fragment_size) {
++ /* The initial check in this function should cover this case */
++ if (frag_header.no == BATADV_FRAG_MAX_FRAGMENTS - 1) {
++ ret = -1;
++ goto out;
++ }
++
+ skb_fragment = batadv_frag_create(skb, &frag_header, mtu);
+ if (!skb_fragment)
+ goto out;
+@@ -507,12 +513,6 @@ int batadv_frag_send_packet(struct sk_bu
+ }
+
+ frag_header.no++;
+-
+- /* The initial check in this function should cover this case */
+- if (frag_header.no == BATADV_FRAG_MAX_FRAGMENTS - 1) {
+- ret = -1;
+- goto out;
+- }
+ }
+
+ /* Make room for the fragment header. */
--- /dev/null
+From foo@baz Tue 17 Mar 2020 11:15:43 AM CET
+From: Sven Eckelmann <sven@narfation.org>
+Date: Mon, 16 Mar 2020 23:30:48 +0100
+Subject: batman-adv: fix TT sync flag inconsistencies
+To: stable@vger.kernel.org
+Cc: "Linus Lüssing" <linus.luessing@c0d3.blue>, "Antonio Quartulli" <a@unstable.cc>, "Simon Wunderlich" <sw@simonwunderlich.de>
+Message-ID: <20200316223105.6333-8-sven@narfation.org>
+
+From: Linus Lüssing <linus.luessing@c0d3.blue>
+
+commit 54e22f265e872ae140755b3318521d400a094605 upstream.
+
+This patch fixes an issue in the translation table code potentially
+leading to a TT Request + Response storm. The issue may occur for nodes
+involving BLA and an inconsistent configuration of the batman-adv AP
+isolation feature. However, since the new multicast optimizations, a
+single, malformed packet may lead to a mesh-wide, persistent
+Denial-of-Service, too.
+
+The issue occurs because nodes are currently OR-ing the TT sync flags of
+all originators announcing a specific MAC address via the
+translation table. When an intermediate node now receives a TT Request
+and wants to answer this on behalf of the destination node, then this
+intermediate node now responds with an altered flag field and broken
+CRC. The next OGM of the real destination will lead to a CRC mismatch
+and triggering a TT Request and Response again.
+
+Furthermore, the OR-ing is currently never undone as long as at least
+one originator announcing the according MAC address remains, leading to
+the potential persistency of this issue.
+
+This patch fixes this issue by storing the flags used in the CRC
+calculation on a a per TT orig entry basis to be able to respond with
+the correct, original flags in an intermediate TT Response for one
+thing. And to be able to correctly unset sync flags once all nodes
+announcing a sync flag vanish for another.
+
+Fixes: e9c00136a475 ("batman-adv: fix tt_global_entries flags update")
+Signed-off-by: Linus Lüssing <linus.luessing@c0d3.blue>
+Acked-by: Antonio Quartulli <a@unstable.cc>
+[sw: typo in commit message]
+Signed-off-by: Simon Wunderlich <sw@simonwunderlich.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/batman-adv/translation-table.c | 60 +++++++++++++++++++++++++++++++------
+ net/batman-adv/types.h | 2 +
+ 2 files changed, 53 insertions(+), 9 deletions(-)
+
+--- a/net/batman-adv/translation-table.c
++++ b/net/batman-adv/translation-table.c
+@@ -1560,9 +1560,41 @@ batadv_tt_global_entry_has_orig(const st
+ return found;
+ }
+
++/**
++ * batadv_tt_global_sync_flags - update TT sync flags
++ * @tt_global: the TT global entry to update sync flags in
++ *
++ * Updates the sync flag bits in the tt_global flag attribute with a logical
++ * OR of all sync flags from any of its TT orig entries.
++ */
++static void
++batadv_tt_global_sync_flags(struct batadv_tt_global_entry *tt_global)
++{
++ struct batadv_tt_orig_list_entry *orig_entry;
++ const struct hlist_head *head;
++ u16 flags = BATADV_NO_FLAGS;
++
++ rcu_read_lock();
++ head = &tt_global->orig_list;
++ hlist_for_each_entry_rcu(orig_entry, head, list)
++ flags |= orig_entry->flags;
++ rcu_read_unlock();
++
++ flags |= tt_global->common.flags & (~BATADV_TT_SYNC_MASK);
++ tt_global->common.flags = flags;
++}
++
++/**
++ * batadv_tt_global_orig_entry_add - add or update a TT orig entry
++ * @tt_global: the TT global entry to add an orig entry in
++ * @orig_node: the originator to add an orig entry for
++ * @ttvn: translation table version number of this changeset
++ * @flags: TT sync flags
++ */
+ static void
+ batadv_tt_global_orig_entry_add(struct batadv_tt_global_entry *tt_global,
+- struct batadv_orig_node *orig_node, int ttvn)
++ struct batadv_orig_node *orig_node, int ttvn,
++ u8 flags)
+ {
+ struct batadv_tt_orig_list_entry *orig_entry;
+
+@@ -1574,7 +1606,8 @@ batadv_tt_global_orig_entry_add(struct b
+ * was added during a "temporary client detection"
+ */
+ orig_entry->ttvn = ttvn;
+- goto out;
++ orig_entry->flags = flags;
++ goto sync_flags;
+ }
+
+ orig_entry = kmem_cache_zalloc(batadv_tt_orig_cache, GFP_ATOMIC);
+@@ -1586,6 +1619,7 @@ batadv_tt_global_orig_entry_add(struct b
+ batadv_tt_global_size_inc(orig_node, tt_global->common.vid);
+ orig_entry->orig_node = orig_node;
+ orig_entry->ttvn = ttvn;
++ orig_entry->flags = flags;
+ kref_init(&orig_entry->refcount);
+
+ kref_get(&orig_entry->refcount);
+@@ -1593,6 +1627,8 @@ batadv_tt_global_orig_entry_add(struct b
+ &tt_global->orig_list);
+ atomic_inc(&tt_global->orig_list_count);
+
++sync_flags:
++ batadv_tt_global_sync_flags(tt_global);
+ out:
+ if (orig_entry)
+ batadv_tt_orig_list_entry_put(orig_entry);
+@@ -1716,10 +1752,10 @@ static bool batadv_tt_global_add(struct
+ }
+
+ /* the change can carry possible "attribute" flags like the
+- * TT_CLIENT_WIFI, therefore they have to be copied in the
++ * TT_CLIENT_TEMP, therefore they have to be copied in the
+ * client entry
+ */
+- common->flags |= flags;
++ common->flags |= flags & (~BATADV_TT_SYNC_MASK);
+
+ /* If there is the BATADV_TT_CLIENT_ROAM flag set, there is only
+ * one originator left in the list and we previously received a
+@@ -1736,7 +1772,8 @@ static bool batadv_tt_global_add(struct
+ }
+ add_orig_entry:
+ /* add the new orig_entry (if needed) or update it */
+- batadv_tt_global_orig_entry_add(tt_global_entry, orig_node, ttvn);
++ batadv_tt_global_orig_entry_add(tt_global_entry, orig_node, ttvn,
++ flags & BATADV_TT_SYNC_MASK);
+
+ batadv_dbg(BATADV_DBG_TT, bat_priv,
+ "Creating new global tt entry: %pM (vid: %d, via %pM)\n",
+@@ -1959,6 +1996,7 @@ batadv_tt_global_dump_subentry(struct sk
+ struct batadv_tt_orig_list_entry *orig,
+ bool best)
+ {
++ u16 flags = (common->flags & (~BATADV_TT_SYNC_MASK)) | orig->flags;
+ void *hdr;
+ struct batadv_orig_node_vlan *vlan;
+ u8 last_ttvn;
+@@ -1988,7 +2026,7 @@ batadv_tt_global_dump_subentry(struct sk
+ nla_put_u8(msg, BATADV_ATTR_TT_LAST_TTVN, last_ttvn) ||
+ nla_put_u32(msg, BATADV_ATTR_TT_CRC32, crc) ||
+ nla_put_u16(msg, BATADV_ATTR_TT_VID, common->vid) ||
+- nla_put_u32(msg, BATADV_ATTR_TT_FLAGS, common->flags))
++ nla_put_u32(msg, BATADV_ATTR_TT_FLAGS, flags))
+ goto nla_put_failure;
+
+ if (best && nla_put_flag(msg, BATADV_ATTR_FLAG_BEST))
+@@ -2602,6 +2640,7 @@ static u32 batadv_tt_global_crc(struct b
+ unsigned short vid)
+ {
+ struct batadv_hashtable *hash = bat_priv->tt.global_hash;
++ struct batadv_tt_orig_list_entry *tt_orig;
+ struct batadv_tt_common_entry *tt_common;
+ struct batadv_tt_global_entry *tt_global;
+ struct hlist_head *head;
+@@ -2640,8 +2679,9 @@ static u32 batadv_tt_global_crc(struct b
+ /* find out if this global entry is announced by this
+ * originator
+ */
+- if (!batadv_tt_global_entry_has_orig(tt_global,
+- orig_node))
++ tt_orig = batadv_tt_global_orig_entry_find(tt_global,
++ orig_node);
++ if (!tt_orig)
+ continue;
+
+ /* use network order to read the VID: this ensures that
+@@ -2653,10 +2693,12 @@ static u32 batadv_tt_global_crc(struct b
+ /* compute the CRC on flags that have to be kept in sync
+ * among nodes
+ */
+- flags = tt_common->flags & BATADV_TT_SYNC_MASK;
++ flags = tt_orig->flags;
+ crc_tmp = crc32c(crc_tmp, &flags, sizeof(flags));
+
+ crc ^= crc32c(crc_tmp, tt_common->addr, ETH_ALEN);
++
++ batadv_tt_orig_list_entry_put(tt_orig);
+ }
+ rcu_read_unlock();
+ }
+--- a/net/batman-adv/types.h
++++ b/net/batman-adv/types.h
+@@ -1241,6 +1241,7 @@ struct batadv_tt_global_entry {
+ * struct batadv_tt_orig_list_entry - orig node announcing a non-mesh client
+ * @orig_node: pointer to orig node announcing this non-mesh client
+ * @ttvn: translation table version number which added the non-mesh client
++ * @flags: per orig entry TT sync flags
+ * @list: list node for batadv_tt_global_entry::orig_list
+ * @refcount: number of contexts the object is used
+ * @rcu: struct used for freeing in an RCU-safe manner
+@@ -1248,6 +1249,7 @@ struct batadv_tt_global_entry {
+ struct batadv_tt_orig_list_entry {
+ struct batadv_orig_node *orig_node;
+ u8 ttvn;
++ u8 flags;
+ struct hlist_node list;
+ struct kref refcount;
+ struct rcu_head rcu;
--- /dev/null
+From foo@baz Tue 17 Mar 2020 11:15:43 AM CET
+From: Sven Eckelmann <sven@narfation.org>
+Date: Mon, 16 Mar 2020 23:30:55 +0100
+Subject: batman-adv: Fix TT sync flags for intermediate TT responses
+To: stable@vger.kernel.org
+Cc: "Linus Lüssing" <linus.luessing@c0d3.blue>, "Leonardo Mörlein" <me@irrelefant.net>, "Sven Eckelmann" <sven@narfation.org>, "Simon Wunderlich" <sw@simonwunderlich.de>
+Message-ID: <20200316223105.6333-15-sven@narfation.org>
+
+From: Linus Lüssing <linus.luessing@c0d3.blue>
+
+commit 7072337e52b3e9d5460500d8dc9cbc1ba2db084c upstream.
+
+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: e9c00136a475 ("batman-adv: fix tt_global_entries flags update")
+Reported-by: Leonardo Mörlein <me@irrelefant.net>
+Signed-off-by: Linus Lüssing <linus.luessing@c0d3.blue>
+Signed-off-by: Sven Eckelmann <sven@narfation.org>
+Signed-off-by: Simon Wunderlich <sw@simonwunderlich.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/batman-adv/translation-table.c | 61 ++++++++++++++++++++++++++++++-------
+ 1 file changed, 51 insertions(+), 10 deletions(-)
+
+--- a/net/batman-adv/translation-table.c
++++ b/net/batman-adv/translation-table.c
+@@ -1539,6 +1539,8 @@ batadv_tt_global_orig_entry_find(const s
+ * 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.
+ *
+@@ -1546,7 +1548,8 @@ batadv_tt_global_orig_entry_find(const s
+ */
+ 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;
+@@ -1554,6 +1557,10 @@ batadv_tt_global_entry_has_orig(const st
+ 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);
+ }
+
+@@ -1734,7 +1741,7 @@ static bool batadv_tt_global_add(struct
+ 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;
+@@ -2876,23 +2883,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;
+@@ -2906,7 +2936,8 @@ static bool batadv_tt_global_valid(const
+ 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);
+ }
+
+ /**
+@@ -2916,25 +2947,34 @@ static bool batadv_tt_global_valid(const
+ * @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];
+@@ -2944,11 +2984,12 @@ static void batadv_tt_tvlv_generate(stru
+ 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));
--- /dev/null
+From foo@baz Tue 17 Mar 2020 11:15:43 AM CET
+From: Sven Eckelmann <sven@narfation.org>
+Date: Mon, 16 Mar 2020 23:30:44 +0100
+Subject: batman-adv: Initialize gw sel_class via batadv_algo
+To: stable@vger.kernel.org
+Cc: Sven Eckelmann <sven@narfation.org>, Simon Wunderlich <sw@simonwunderlich.de>
+Message-ID: <20200316223105.6333-4-sven@narfation.org>
+
+From: Sven Eckelmann <sven@narfation.org>
+
+commit 1a9070ec91b37234fe915849b767c61584c64a44 upstream.
+
+The gateway selection class variable is shared between different algorithm
+versions. But the interpretation of the content is algorithm specific. The
+initialization is therefore also algorithm specific.
+
+But this was implemented incorrectly and the initialization for BATMAN_V
+always overwrote the value previously written for BATMAN_IV. This could
+only be avoided when BATMAN_V was disabled during compile time.
+
+Using a special batadv_algo hook for this initialization avoids this
+problem.
+
+Fixes: 50164d8f500f ("batman-adv: B.A.T.M.A.N. V - implement GW selection logic")
+Signed-off-by: Sven Eckelmann <sven@narfation.org>
+Signed-off-by: Simon Wunderlich <sw@simonwunderlich.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/batman-adv/bat_iv_ogm.c | 11 +++++++++++
+ net/batman-adv/bat_v.c | 14 +++++++++++---
+ net/batman-adv/gateway_common.c | 5 +++++
+ net/batman-adv/soft-interface.c | 1 -
+ net/batman-adv/types.h | 2 ++
+ 5 files changed, 29 insertions(+), 4 deletions(-)
+
+--- a/net/batman-adv/bat_iv_ogm.c
++++ b/net/batman-adv/bat_iv_ogm.c
+@@ -2479,6 +2479,16 @@ static void batadv_iv_iface_activate(str
+ batadv_iv_ogm_schedule(hard_iface);
+ }
+
++/**
++ * batadv_iv_init_sel_class - initialize GW selection class
++ * @bat_priv: the bat priv with all the soft interface information
++ */
++static void batadv_iv_init_sel_class(struct batadv_priv *bat_priv)
++{
++ /* set default TQ difference threshold to 20 */
++ atomic_set(&bat_priv->gw.sel_class, 20);
++}
++
+ static struct batadv_gw_node *
+ batadv_iv_gw_get_best_gw_node(struct batadv_priv *bat_priv)
+ {
+@@ -2827,6 +2837,7 @@ static struct batadv_algo_ops batadv_bat
+ .del_if = batadv_iv_ogm_orig_del_if,
+ },
+ .gw = {
++ .init_sel_class = batadv_iv_init_sel_class,
+ .get_best_gw_node = batadv_iv_gw_get_best_gw_node,
+ .is_eligible = batadv_iv_gw_is_eligible,
+ #ifdef CONFIG_BATMAN_ADV_DEBUGFS
+--- a/net/batman-adv/bat_v.c
++++ b/net/batman-adv/bat_v.c
+@@ -668,6 +668,16 @@ err_ifinfo1:
+ return ret;
+ }
+
++/**
++ * batadv_v_init_sel_class - initialize GW selection class
++ * @bat_priv: the bat priv with all the soft interface information
++ */
++static void batadv_v_init_sel_class(struct batadv_priv *bat_priv)
++{
++ /* set default throughput difference threshold to 5Mbps */
++ atomic_set(&bat_priv->gw.sel_class, 50);
++}
++
+ static ssize_t batadv_v_store_sel_class(struct batadv_priv *bat_priv,
+ char *buff, size_t count)
+ {
+@@ -1054,6 +1064,7 @@ static struct batadv_algo_ops batadv_bat
+ .dump = batadv_v_orig_dump,
+ },
+ .gw = {
++ .init_sel_class = batadv_v_init_sel_class,
+ .store_sel_class = batadv_v_store_sel_class,
+ .show_sel_class = batadv_v_show_sel_class,
+ .get_best_gw_node = batadv_v_gw_get_best_gw_node,
+@@ -1094,9 +1105,6 @@ int batadv_v_mesh_init(struct batadv_pri
+ if (ret < 0)
+ return ret;
+
+- /* set default throughput difference threshold to 5Mbps */
+- atomic_set(&bat_priv->gw.sel_class, 50);
+-
+ return 0;
+ }
+
+--- a/net/batman-adv/gateway_common.c
++++ b/net/batman-adv/gateway_common.c
+@@ -253,6 +253,11 @@ static void batadv_gw_tvlv_ogm_handler_v
+ */
+ void batadv_gw_init(struct batadv_priv *bat_priv)
+ {
++ if (bat_priv->algo_ops->gw.init_sel_class)
++ bat_priv->algo_ops->gw.init_sel_class(bat_priv);
++ else
++ atomic_set(&bat_priv->gw.sel_class, 1);
++
+ batadv_tvlv_handler_register(bat_priv, batadv_gw_tvlv_ogm_handler_v1,
+ NULL, BATADV_TVLV_GW, 1,
+ BATADV_TVLV_HANDLER_OGM_CIFNOTFND);
+--- a/net/batman-adv/soft-interface.c
++++ b/net/batman-adv/soft-interface.c
+@@ -808,7 +808,6 @@ static int batadv_softif_init_late(struc
+ atomic_set(&bat_priv->mcast.num_want_all_ipv6, 0);
+ #endif
+ atomic_set(&bat_priv->gw.mode, BATADV_GW_MODE_OFF);
+- atomic_set(&bat_priv->gw.sel_class, 20);
+ atomic_set(&bat_priv->gw.bandwidth_down, 100);
+ atomic_set(&bat_priv->gw.bandwidth_up, 20);
+ atomic_set(&bat_priv->orig_interval, 1000);
+--- a/net/batman-adv/types.h
++++ b/net/batman-adv/types.h
+@@ -1466,6 +1466,7 @@ struct batadv_algo_orig_ops {
+
+ /**
+ * struct batadv_algo_gw_ops - mesh algorithm callbacks (GW specific)
++ * @init_sel_class: initialize GW selection class (optional)
+ * @store_sel_class: parse and stores a new GW selection class (optional)
+ * @show_sel_class: prints the current GW selection class (optional)
+ * @get_best_gw_node: select the best GW from the list of available nodes
+@@ -1476,6 +1477,7 @@ struct batadv_algo_orig_ops {
+ * @dump: dump gateways to a netlink socket (optional)
+ */
+ struct batadv_algo_gw_ops {
++ void (*init_sel_class)(struct batadv_priv *bat_priv);
+ ssize_t (*store_sel_class)(struct batadv_priv *bat_priv, char *buff,
+ size_t count);
+ ssize_t (*show_sel_class)(struct batadv_priv *bat_priv, char *buff);
--- /dev/null
+From foo@baz Tue 17 Mar 2020 11:15:44 AM CET
+From: Sven Eckelmann <sven@narfation.org>
+Date: Mon, 16 Mar 2020 23:31:01 +0100
+Subject: batman-adv: Prevent duplicated gateway_node entry
+To: stable@vger.kernel.org
+Cc: Sven Eckelmann <sven@narfation.org>, Marek Lindner <mareklindner@neomailbox.ch>, Simon Wunderlich <sw@simonwunderlich.de>
+Message-ID: <20200316223105.6333-21-sven@narfation.org>
+
+From: Sven Eckelmann <sven@narfation.org>
+
+commit dff9bc42ab0b2d38c5e90ddd79b238fed5b4c7ad upstream.
+
+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: c6c8fea29769 ("net: Add batman-adv meshing protocol")
+Signed-off-by: Sven Eckelmann <sven@narfation.org>
+Acked-by: Marek Lindner <mareklindner@neomailbox.ch>
+Signed-off-by: Simon Wunderlich <sw@simonwunderlich.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/batman-adv/gateway_client.c | 11 +++++++++--
+ 1 file changed, 9 insertions(+), 2 deletions(-)
+
+--- a/net/batman-adv/gateway_client.c
++++ b/net/batman-adv/gateway_client.c
+@@ -31,6 +31,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>
+@@ -325,6 +326,9 @@ out:
+ * @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,
+@@ -332,6 +336,8 @@ static void batadv_gw_node_add(struct ba
+ {
+ struct batadv_gw_node *gw_node;
+
++ lockdep_assert_held(&bat_priv->gw.list_lock);
++
+ if (gateway->bandwidth_down == 0)
+ return;
+
+@@ -346,10 +352,8 @@ static void batadv_gw_node_add(struct ba
+ 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.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",
+@@ -404,11 +408,14 @@ void batadv_gw_node_update(struct batadv
+ {
+ 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)))
--- /dev/null
+From foo@baz Tue 17 Mar 2020 11:15:43 AM CET
+From: Sven Eckelmann <sven@narfation.org>
+Date: Mon, 16 Mar 2020 23:30:56 +0100
+Subject: batman-adv: prevent TT request storms by not sending inconsistent TT TLVLs
+To: stable@vger.kernel.org
+Cc: Marek Lindner <mareklindner@neomailbox.ch>, Sven Eckelmann <sven@narfation.org>, Simon Wunderlich <sw@simonwunderlich.de>
+Message-ID: <20200316223105.6333-16-sven@narfation.org>
+
+From: Marek Lindner <mareklindner@neomailbox.ch>
+
+commit 16116dac23396e73c01eeee97b102e4833a4b205 upstream.
+
+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>
+Signed-off-by: Simon Wunderlich <sw@simonwunderlich.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/batman-adv/translation-table.c | 15 ++++++++++++---
+ 1 file changed, 12 insertions(+), 3 deletions(-)
+
+--- a/net/batman-adv/translation-table.c
++++ b/net/batman-adv/translation-table.c
+@@ -936,15 +936,20 @@ batadv_tt_prepare_tvlv_local_data(struct
+ 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);
+@@ -952,7 +957,7 @@ batadv_tt_prepare_tvlv_local_data(struct
+
+ /* 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;
+@@ -969,6 +974,10 @@ batadv_tt_prepare_tvlv_local_data(struct
+
+ 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);
+
--- /dev/null
+From foo@baz Tue 17 Mar 2020 11:15:43 AM CET
+From: Sven Eckelmann <sven@narfation.org>
+Date: Mon, 16 Mar 2020 23:30:46 +0100
+Subject: batman-adv: Use default throughput value on cfg80211 error
+To: stable@vger.kernel.org
+Cc: Sven Eckelmann <sven@narfation.org>, Marek Lindner <mareklindner@neomailbox.ch>, Simon Wunderlich <sw@simonwunderlich.de>
+Message-ID: <20200316223105.6333-6-sven@narfation.org>
+
+From: Sven Eckelmann <sven@narfation.org>
+
+commit 3f3f87325dcb3c201076c81490f4da91ad4c09fc upstream.
+
+A wifi interface should never be handled like an ethernet devices. The
+parser of the cfg80211 output must therefore skip the ethtool code when
+cfg80211_get_station returned an error.
+
+Fixes: f44a3ae9a281 ("batman-adv: refactor wifi interface detection")
+Signed-off-by: Sven Eckelmann <sven@narfation.org>
+Reviewed-by: Marek Lindner <mareklindner@neomailbox.ch>
+Signed-off-by: Simon Wunderlich <sw@simonwunderlich.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/batman-adv/bat_v_elp.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+--- a/net/batman-adv/bat_v_elp.c
++++ b/net/batman-adv/bat_v_elp.c
+@@ -100,8 +100,10 @@ static u32 batadv_v_elp_get_throughput(s
+ */
+ return 0;
+ }
+- if (!ret)
+- return sinfo.expected_throughput / 100;
++ if (ret)
++ goto default_throughput;
++
++ return sinfo.expected_throughput / 100;
+ }
+
+ /* unsupported WiFi driver version */
iommu-vt-d-ignore-devices-with-out-of-spec-domain-number.patch
ipv6-restrict-ipv6_addrform-operation.patch
efi-add-a-sanity-check-to-efivar_store_raw.patch
+batman-adv-fix-double-free-during-fragment-merge-error.patch
+batman-adv-fix-transmission-of-final-16th-fragment.patch
+batman-adv-initialize-gw-sel_class-via-batadv_algo.patch
+batman-adv-fix-rx-packet-bytes-stats-on-local-arp-reply.patch
+batman-adv-use-default-throughput-value-on-cfg80211-error.patch
+batman-adv-accept-only-filled-wifi-station-info.patch
+batman-adv-fix-tt-sync-flag-inconsistencies.patch
+batman-adv-avoid-spurious-warnings-from-bat_v-neigh_cmp-implementation.patch
+batman-adv-always-initialize-fragment-header-priority.patch
+batman-adv-fix-check-of-retrieved-orig_gw-in-batadv_v_gw_is_eligible.patch
+batman-adv-fix-lock-for-ogm-cnt-access-in-batadv_iv_ogm_calc_tq.patch
+batman-adv-fix-internal-interface-indices-types.patch
+batman-adv-avoid-race-in-tt-tvlv-allocator-helper.patch
+batman-adv-fix-tt-sync-flags-for-intermediate-tt-responses.patch
+batman-adv-prevent-tt-request-storms-by-not-sending-inconsistent-tt-tlvls.patch
+batman-adv-fix-debugfs-path-for-renamed-hardif.patch
+batman-adv-fix-debugfs-path-for-renamed-softif.patch
+batman-adv-avoid-storing-non-tt-sync-flags-on-singular-entries-too.patch
+batman-adv-fix-multicast-tt-issues-with-bogus-roam-flags.patch
+batman-adv-prevent-duplicated-gateway_node-entry.patch
+batman-adv-fix-duplicated-ogms-on-netdev_up.patch
+batman-adv-avoid-free-alloc-race-when-handling-ogm2-buffer.patch
+batman-adv-avoid-free-alloc-race-when-handling-ogm-buffer.patch
+batman-adv-don-t-schedule-ogm-for-disabled-interface.patch