From: Greg Kroah-Hartman Date: Tue, 17 Mar 2020 10:19:40 +0000 (+0100) Subject: 4.9-stable patches X-Git-Tag: v4.19.111~2 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=5dd3e054eb6ae3ba82d4afeb3938651fb246644c;p=thirdparty%2Fkernel%2Fstable-queue.git 4.9-stable patches added patches: batman-adv-accept-only-filled-wifi-station-info.patch batman-adv-always-initialize-fragment-header-priority.patch batman-adv-avoid-free-alloc-race-when-handling-ogm-buffer.patch batman-adv-avoid-free-alloc-race-when-handling-ogm2-buffer.patch batman-adv-avoid-race-in-tt-tvlv-allocator-helper.patch batman-adv-avoid-spurious-warnings-from-bat_v-neigh_cmp-implementation.patch batman-adv-avoid-storing-non-tt-sync-flags-on-singular-entries-too.patch batman-adv-don-t-schedule-ogm-for-disabled-interface.patch batman-adv-fix-check-of-retrieved-orig_gw-in-batadv_v_gw_is_eligible.patch batman-adv-fix-debugfs-path-for-renamed-hardif.patch batman-adv-fix-debugfs-path-for-renamed-softif.patch batman-adv-fix-double-free-during-fragment-merge-error.patch batman-adv-fix-duplicated-ogms-on-netdev_up.patch batman-adv-fix-internal-interface-indices-types.patch batman-adv-fix-lock-for-ogm-cnt-access-in-batadv_iv_ogm_calc_tq.patch batman-adv-fix-multicast-tt-issues-with-bogus-roam-flags.patch batman-adv-fix-rx-packet-bytes-stats-on-local-arp-reply.patch batman-adv-fix-transmission-of-final-16th-fragment.patch batman-adv-fix-tt-sync-flag-inconsistencies.patch batman-adv-fix-tt-sync-flags-for-intermediate-tt-responses.patch batman-adv-initialize-gw-sel_class-via-batadv_algo.patch batman-adv-prevent-duplicated-gateway_node-entry.patch batman-adv-prevent-tt-request-storms-by-not-sending-inconsistent-tt-tlvls.patch batman-adv-use-default-throughput-value-on-cfg80211-error.patch --- diff --git a/queue-4.9/batman-adv-accept-only-filled-wifi-station-info.patch b/queue-4.9/batman-adv-accept-only-filled-wifi-station-info.patch new file mode 100644 index 00000000000..7847f4794b0 --- /dev/null +++ b/queue-4.9/batman-adv-accept-only-filled-wifi-station-info.patch @@ -0,0 +1,57 @@ +From foo@baz Tue 17 Mar 2020 11:15:43 AM CET +From: Sven Eckelmann +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 , Alvaro Antelo , Marek Lindner , Simon Wunderlich +Message-ID: <20200316223105.6333-7-sven@narfation.org> + +From: Sven Eckelmann + +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 +Fixes: c833484e5f38 ("batman-adv: ELP - compute the metric based on the estimated throughput") +Signed-off-by: Sven Eckelmann +Reviewed-by: Marek Lindner +Signed-off-by: Simon Wunderlich +Signed-off-by: Greg Kroah-Hartman +--- + 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 ++#include + #include + #include + #include +@@ -29,6 +30,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -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; + } diff --git a/queue-4.9/batman-adv-always-initialize-fragment-header-priority.patch b/queue-4.9/batman-adv-always-initialize-fragment-header-priority.patch new file mode 100644 index 00000000000..611bda6b4ac --- /dev/null +++ b/queue-4.9/batman-adv-always-initialize-fragment-header-priority.patch @@ -0,0 +1,36 @@ +From foo@baz Tue 17 Mar 2020 11:15:43 AM CET +From: Sven Eckelmann +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 , Simon Wunderlich +Message-ID: <20200316223105.6333-10-sven@narfation.org> + +From: Sven Eckelmann + +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 +Signed-off-by: Simon Wunderlich +Signed-off-by: Greg Kroah-Hartman +--- + 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); diff --git a/queue-4.9/batman-adv-avoid-free-alloc-race-when-handling-ogm-buffer.patch b/queue-4.9/batman-adv-avoid-free-alloc-race-when-handling-ogm-buffer.patch new file mode 100644 index 00000000000..1490791e214 --- /dev/null +++ b/queue-4.9/batman-adv-avoid-free-alloc-race-when-handling-ogm-buffer.patch @@ -0,0 +1,205 @@ +From foo@baz Tue 17 Mar 2020 11:15:44 AM CET +From: Sven Eckelmann +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 , syzbot+0cc629f19ccb8534935b@syzkaller.appspotmail.com, Simon Wunderlich +Message-ID: <20200316223105.6333-24-sven@narfation.org> + +From: Sven Eckelmann + +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 +Signed-off-by: Simon Wunderlich +Signed-off-by: Greg Kroah-Hartman +--- + 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 + #include + #include ++#include + #include + #include + #include +@@ -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 + #include + #include ++#include + #include + #include + #include +@@ -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; + }; + + /** diff --git a/queue-4.9/batman-adv-avoid-free-alloc-race-when-handling-ogm2-buffer.patch b/queue-4.9/batman-adv-avoid-free-alloc-race-when-handling-ogm2-buffer.patch new file mode 100644 index 00000000000..78401937779 --- /dev/null +++ b/queue-4.9/batman-adv-avoid-free-alloc-race-when-handling-ogm2-buffer.patch @@ -0,0 +1,157 @@ +From foo@baz Tue 17 Mar 2020 11:15:44 AM CET +From: Sven Eckelmann +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 , Simon Wunderlich +Message-ID: <20200316223105.6333-23-sven@narfation.org> + +From: Sven Eckelmann + +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 +Signed-off-by: Simon Wunderlich +Signed-off-by: Greg Kroah-Hartman +--- + 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 + #include + #include ++#include ++#include + #include + #include + #include +@@ -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 + #include + #include ++#include + #include + #include + #include /* 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; + }; + diff --git a/queue-4.9/batman-adv-avoid-race-in-tt-tvlv-allocator-helper.patch b/queue-4.9/batman-adv-avoid-race-in-tt-tvlv-allocator-helper.patch new file mode 100644 index 00000000000..2021a8eefec --- /dev/null +++ b/queue-4.9/batman-adv-avoid-race-in-tt-tvlv-allocator-helper.patch @@ -0,0 +1,81 @@ +From foo@baz Tue 17 Mar 2020 11:15:43 AM CET +From: Sven Eckelmann +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 , Antonio Quartulli , Simon Wunderlich +Message-ID: <20200316223105.6333-14-sven@narfation.org> + +From: Sven Eckelmann + +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 +Acked-by: Antonio Quartulli +Signed-off-by: Simon Wunderlich +Signed-off-by: Greg Kroah-Hartman +--- + 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; + } + diff --git a/queue-4.9/batman-adv-avoid-spurious-warnings-from-bat_v-neigh_cmp-implementation.patch b/queue-4.9/batman-adv-avoid-spurious-warnings-from-bat_v-neigh_cmp-implementation.patch new file mode 100644 index 00000000000..8e43b5bd53b --- /dev/null +++ b/queue-4.9/batman-adv-avoid-spurious-warnings-from-bat_v-neigh_cmp-implementation.patch @@ -0,0 +1,69 @@ +From foo@baz Tue 17 Mar 2020 11:15:43 AM CET +From: Sven Eckelmann +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 , Simon Wunderlich +Message-ID: <20200316223105.6333-9-sven@narfation.org> + +From: Sven Eckelmann + +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 +Signed-off-by: Simon Wunderlich +Signed-off-by: Greg Kroah-Hartman +--- + 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 +-#include + #include + #include + #include +@@ -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; diff --git a/queue-4.9/batman-adv-avoid-storing-non-tt-sync-flags-on-singular-entries-too.patch b/queue-4.9/batman-adv-avoid-storing-non-tt-sync-flags-on-singular-entries-too.patch new file mode 100644 index 00000000000..06c936f56c1 --- /dev/null +++ b/queue-4.9/batman-adv-avoid-storing-non-tt-sync-flags-on-singular-entries-too.patch @@ -0,0 +1,43 @@ +From foo@baz Tue 17 Mar 2020 11:15:43 AM CET +From: Sven Eckelmann +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" , "Sven Eckelmann" , "Simon Wunderlich" +Message-ID: <20200316223105.6333-19-sven@narfation.org> + +From: Linus Lüssing + +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 +Signed-off-by: Sven Eckelmann +Signed-off-by: Simon Wunderlich +Signed-off-by: Greg Kroah-Hartman +--- + 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 diff --git a/queue-4.9/batman-adv-don-t-schedule-ogm-for-disabled-interface.patch b/queue-4.9/batman-adv-don-t-schedule-ogm-for-disabled-interface.patch new file mode 100644 index 00000000000..0941780eb8f --- /dev/null +++ b/queue-4.9/batman-adv-don-t-schedule-ogm-for-disabled-interface.patch @@ -0,0 +1,43 @@ +From foo@baz Tue 17 Mar 2020 11:15:44 AM CET +From: Sven Eckelmann +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 , syzbot+a98f2016f40b9cd3818a@syzkaller.appspotmail.com, syzbot+ac36b6a33c28a491e929@syzkaller.appspotmail.com, Hillf Danton , Simon Wunderlich +Message-ID: <20200316223105.6333-25-sven@narfation.org> + +From: Sven Eckelmann + +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 +Cc: Hillf Danton +Signed-off-by: Simon Wunderlich +Signed-off-by: Greg Kroah-Hartman +--- + 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 diff --git a/queue-4.9/batman-adv-fix-check-of-retrieved-orig_gw-in-batadv_v_gw_is_eligible.patch b/queue-4.9/batman-adv-fix-check-of-retrieved-orig_gw-in-batadv_v_gw_is_eligible.patch new file mode 100644 index 00000000000..27c032c5752 --- /dev/null +++ b/queue-4.9/batman-adv-fix-check-of-retrieved-orig_gw-in-batadv_v_gw_is_eligible.patch @@ -0,0 +1,37 @@ +From foo@baz Tue 17 Mar 2020 11:15:43 AM CET +From: Sven Eckelmann +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 , Antonio Quartulli , Simon Wunderlich +Message-ID: <20200316223105.6333-11-sven@narfation.org> + +From: Sven Eckelmann + +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 +Acked-by: Antonio Quartulli +Signed-off-by: Simon Wunderlich +Signed-off-by: Greg Kroah-Hartman +--- + 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) diff --git a/queue-4.9/batman-adv-fix-debugfs-path-for-renamed-hardif.patch b/queue-4.9/batman-adv-fix-debugfs-path-for-renamed-hardif.patch new file mode 100644 index 00000000000..ab2418ad87a --- /dev/null +++ b/queue-4.9/batman-adv-fix-debugfs-path-for-renamed-hardif.patch @@ -0,0 +1,113 @@ +From foo@baz Tue 17 Mar 2020 11:15:43 AM CET +From: Sven Eckelmann +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 , John Soros , Simon Wunderlich +Message-ID: <20200316223105.6333-17-sven@narfation.org> + +From: Sven Eckelmann + +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 +Signed-off-by: Sven Eckelmann +Signed-off-by: Simon Wunderlich +Signed-off-by: Greg Kroah-Hartman +--- + 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 + #include + #include + #include +@@ -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; + } diff --git a/queue-4.9/batman-adv-fix-debugfs-path-for-renamed-softif.patch b/queue-4.9/batman-adv-fix-debugfs-path-for-renamed-softif.patch new file mode 100644 index 00000000000..6a09c686699 --- /dev/null +++ b/queue-4.9/batman-adv-fix-debugfs-path-for-renamed-softif.patch @@ -0,0 +1,141 @@ +From foo@baz Tue 17 Mar 2020 11:15:43 AM CET +From: Sven Eckelmann +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 , Simon Wunderlich +Message-ID: <20200316223105.6333-18-sven@narfation.org> + +From: Sven Eckelmann + +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 +Signed-off-by: Simon Wunderlich +Signed-off-by: Greg Kroah-Hartman +--- + 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 || diff --git a/queue-4.9/batman-adv-fix-double-free-during-fragment-merge-error.patch b/queue-4.9/batman-adv-fix-double-free-during-fragment-merge-error.patch new file mode 100644 index 00000000000..d474a5c8047 --- /dev/null +++ b/queue-4.9/batman-adv-fix-double-free-during-fragment-merge-error.patch @@ -0,0 +1,83 @@ +From foo@baz Tue 17 Mar 2020 11:15:43 AM CET +From: Sven Eckelmann +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 , Simon Wunderlich +Message-ID: <20200316223105.6333-2-sven@narfation.org> + +From: Sven Eckelmann + +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 +Signed-off-by: Simon Wunderlich +Signed-off-by: Greg Kroah-Hartman +--- + 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; diff --git a/queue-4.9/batman-adv-fix-duplicated-ogms-on-netdev_up.patch b/queue-4.9/batman-adv-fix-duplicated-ogms-on-netdev_up.patch new file mode 100644 index 00000000000..0750698324e --- /dev/null +++ b/queue-4.9/batman-adv-fix-duplicated-ogms-on-netdev_up.patch @@ -0,0 +1,92 @@ +From foo@baz Tue 17 Mar 2020 11:15:44 AM CET +From: Sven Eckelmann +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" , "Linus Lüssing" , "Marek Lindner" , "Simon Wunderlich" +Message-ID: <20200316223105.6333-22-sven@narfation.org> + +From: Sven Eckelmann + +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 +Tested-by: Linus Lüssing +Acked-by: Marek Lindner +Signed-off-by: Sven Eckelmann +Signed-off-by: Simon Wunderlich +Signed-off-by: Greg Kroah-Hartman +--- + 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); diff --git a/queue-4.9/batman-adv-fix-internal-interface-indices-types.patch b/queue-4.9/batman-adv-fix-internal-interface-indices-types.patch new file mode 100644 index 00000000000..5b5e5086709 --- /dev/null +++ b/queue-4.9/batman-adv-fix-internal-interface-indices-types.patch @@ -0,0 +1,237 @@ +From foo@baz Tue 17 Mar 2020 11:15:43 AM CET +From: Sven Eckelmann +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 , Simon Wunderlich +Message-ID: <20200316223105.6333-13-sven@narfation.org> + +From: Sven Eckelmann + +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 +Signed-off-by: Simon Wunderlich +Signed-off-by: Greg Kroah-Hartman +--- + 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); diff --git a/queue-4.9/batman-adv-fix-lock-for-ogm-cnt-access-in-batadv_iv_ogm_calc_tq.patch b/queue-4.9/batman-adv-fix-lock-for-ogm-cnt-access-in-batadv_iv_ogm_calc_tq.patch new file mode 100644 index 00000000000..d78676db18b --- /dev/null +++ b/queue-4.9/batman-adv-fix-lock-for-ogm-cnt-access-in-batadv_iv_ogm_calc_tq.patch @@ -0,0 +1,47 @@ +From foo@baz Tue 17 Mar 2020 11:15:43 AM CET +From: Sven Eckelmann +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 , Simon Wunderlich +Message-ID: <20200316223105.6333-12-sven@narfation.org> + +From: Sven Eckelmann + +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 +Signed-off-by: Simon Wunderlich +Signed-off-by: Greg Kroah-Hartman +--- + 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) diff --git a/queue-4.9/batman-adv-fix-multicast-tt-issues-with-bogus-roam-flags.patch b/queue-4.9/batman-adv-fix-multicast-tt-issues-with-bogus-roam-flags.patch new file mode 100644 index 00000000000..0b0612d81a6 --- /dev/null +++ b/queue-4.9/batman-adv-fix-multicast-tt-issues-with-bogus-roam-flags.patch @@ -0,0 +1,51 @@ +From foo@baz Tue 17 Mar 2020 11:15:44 AM CET +From: Sven Eckelmann +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" , "Leonardo Mörlein" , "Simon Wunderlich" +Message-ID: <20200316223105.6333-20-sven@narfation.org> + +From: Linus Lüssing + +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 +Signed-off-by: Linus Lüssing +Signed-off-by: Simon Wunderlich +Signed-off-by: Greg Kroah-Hartman +--- + 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 diff --git a/queue-4.9/batman-adv-fix-rx-packet-bytes-stats-on-local-arp-reply.patch b/queue-4.9/batman-adv-fix-rx-packet-bytes-stats-on-local-arp-reply.patch new file mode 100644 index 00000000000..47ced4c9f2b --- /dev/null +++ b/queue-4.9/batman-adv-fix-rx-packet-bytes-stats-on-local-arp-reply.patch @@ -0,0 +1,42 @@ +From foo@baz Tue 17 Mar 2020 11:15:43 AM CET +From: Sven Eckelmann +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 , Simon Wunderlich +Message-ID: <20200316223105.6333-5-sven@narfation.org> + +From: Sven Eckelmann + +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 +Signed-off-by: Simon Wunderlich +Signed-off-by: Greg Kroah-Hartman +--- + 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); diff --git a/queue-4.9/batman-adv-fix-transmission-of-final-16th-fragment.patch b/queue-4.9/batman-adv-fix-transmission-of-final-16th-fragment.patch new file mode 100644 index 00000000000..5884dafa7ab --- /dev/null +++ b/queue-4.9/batman-adv-fix-transmission-of-final-16th-fragment.patch @@ -0,0 +1,60 @@ +From foo@baz Tue 17 Mar 2020 11:15:43 AM CET +From: Sven Eckelmann +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" , "Sven Eckelmann" , "Simon Wunderlich" +Message-ID: <20200316223105.6333-3-sven@narfation.org> + +From: Linus Lüssing + +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 +Signed-off-by: Sven Eckelmann +Signed-off-by: Simon Wunderlich +Signed-off-by: Greg Kroah-Hartman +--- + 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. */ diff --git a/queue-4.9/batman-adv-fix-tt-sync-flag-inconsistencies.patch b/queue-4.9/batman-adv-fix-tt-sync-flag-inconsistencies.patch new file mode 100644 index 00000000000..8a754c5b0e4 --- /dev/null +++ b/queue-4.9/batman-adv-fix-tt-sync-flag-inconsistencies.patch @@ -0,0 +1,212 @@ +From foo@baz Tue 17 Mar 2020 11:15:43 AM CET +From: Sven Eckelmann +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" , "Antonio Quartulli" , "Simon Wunderlich" +Message-ID: <20200316223105.6333-8-sven@narfation.org> + +From: Linus Lüssing + +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 +Acked-by: Antonio Quartulli +[sw: typo in commit message] +Signed-off-by: Simon Wunderlich +Signed-off-by: Greg Kroah-Hartman +--- + 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; diff --git a/queue-4.9/batman-adv-fix-tt-sync-flags-for-intermediate-tt-responses.patch b/queue-4.9/batman-adv-fix-tt-sync-flags-for-intermediate-tt-responses.patch new file mode 100644 index 00000000000..03786fbb099 --- /dev/null +++ b/queue-4.9/batman-adv-fix-tt-sync-flags-for-intermediate-tt-responses.patch @@ -0,0 +1,187 @@ +From foo@baz Tue 17 Mar 2020 11:15:43 AM CET +From: Sven Eckelmann +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" , "Leonardo Mörlein" , "Sven Eckelmann" , "Simon Wunderlich" +Message-ID: <20200316223105.6333-15-sven@narfation.org> + +From: Linus Lüssing + +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 +Signed-off-by: Linus Lüssing +Signed-off-by: Sven Eckelmann +Signed-off-by: Simon Wunderlich +Signed-off-by: Greg Kroah-Hartman +--- + 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)); diff --git a/queue-4.9/batman-adv-initialize-gw-sel_class-via-batadv_algo.patch b/queue-4.9/batman-adv-initialize-gw-sel_class-via-batadv_algo.patch new file mode 100644 index 00000000000..e25fdc6b784 --- /dev/null +++ b/queue-4.9/batman-adv-initialize-gw-sel_class-via-batadv_algo.patch @@ -0,0 +1,141 @@ +From foo@baz Tue 17 Mar 2020 11:15:43 AM CET +From: Sven Eckelmann +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 , Simon Wunderlich +Message-ID: <20200316223105.6333-4-sven@narfation.org> + +From: Sven Eckelmann + +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 +Signed-off-by: Simon Wunderlich +Signed-off-by: Greg Kroah-Hartman +--- + 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); diff --git a/queue-4.9/batman-adv-prevent-duplicated-gateway_node-entry.patch b/queue-4.9/batman-adv-prevent-duplicated-gateway_node-entry.patch new file mode 100644 index 00000000000..421c6bf2bc0 --- /dev/null +++ b/queue-4.9/batman-adv-prevent-duplicated-gateway_node-entry.patch @@ -0,0 +1,87 @@ +From foo@baz Tue 17 Mar 2020 11:15:44 AM CET +From: Sven Eckelmann +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 , Marek Lindner , Simon Wunderlich +Message-ID: <20200316223105.6333-21-sven@narfation.org> + +From: Sven Eckelmann + +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 +Acked-by: Marek Lindner +Signed-off-by: Simon Wunderlich +Signed-off-by: Greg Kroah-Hartman +--- + 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 + #include + #include ++#include + #include + #include + #include +@@ -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))) diff --git a/queue-4.9/batman-adv-prevent-tt-request-storms-by-not-sending-inconsistent-tt-tlvls.patch b/queue-4.9/batman-adv-prevent-tt-request-storms-by-not-sending-inconsistent-tt-tlvls.patch new file mode 100644 index 00000000000..dc023b4e6b7 --- /dev/null +++ b/queue-4.9/batman-adv-prevent-tt-request-storms-by-not-sending-inconsistent-tt-tlvls.patch @@ -0,0 +1,82 @@ +From foo@baz Tue 17 Mar 2020 11:15:43 AM CET +From: Sven Eckelmann +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 , Sven Eckelmann , Simon Wunderlich +Message-ID: <20200316223105.6333-16-sven@narfation.org> + +From: Marek Lindner + +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 +Signed-off-by: Sven Eckelmann +Signed-off-by: Simon Wunderlich +Signed-off-by: Greg Kroah-Hartman +--- + 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); + diff --git a/queue-4.9/batman-adv-use-default-throughput-value-on-cfg80211-error.patch b/queue-4.9/batman-adv-use-default-throughput-value-on-cfg80211-error.patch new file mode 100644 index 00000000000..15fde5fc4fe --- /dev/null +++ b/queue-4.9/batman-adv-use-default-throughput-value-on-cfg80211-error.patch @@ -0,0 +1,40 @@ +From foo@baz Tue 17 Mar 2020 11:15:43 AM CET +From: Sven Eckelmann +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 , Marek Lindner , Simon Wunderlich +Message-ID: <20200316223105.6333-6-sven@narfation.org> + +From: Sven Eckelmann + +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 +Reviewed-by: Marek Lindner +Signed-off-by: Simon Wunderlich +Signed-off-by: Greg Kroah-Hartman +--- + 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 */ diff --git a/queue-4.9/series b/queue-4.9/series index 3869d3ac812..1344900afd7 100644 --- a/queue-4.9/series +++ b/queue-4.9/series @@ -48,3 +48,27 @@ iommu-vt-d-fix-the-wrong-printing-in-rhsa-parsing.patch 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