From 2ac8e7b42b034cf9f4d1507f280e08739fd80685 Mon Sep 17 00:00:00 2001 From: Sven Eckelmann Date: Sat, 15 Sep 2018 11:04:04 +0200 Subject: [PATCH] batman-adv: Merge bugfixes from 2018.3 * Avoid probe ELP information leak * Fix segfault when writing to throughput_override * Fix segfault when writing to sysfs elp_interval * fix backbone_gw refcount on queue_work() failure * fix hardif_neigh refcount on queue_work() failure * Prevent duplicated gateway_node entry * Prevent duplicated nc_node entry * Prevent duplicated softif_vlan entry * Prevent duplicated global TT entry * Prevent duplicated tvlv handler Signed-off-by: Sven Eckelmann --- batman-adv/Makefile | 2 +- batman-adv/files/compat-hacks.h | 29 +++++ ...adv-Avoid-probe-ELP-information-leak.patch | 35 ++++++ ...egfault-when-writing-to-throughput_o.patch | 45 ++++++++ ...egfault-when-writing-to-sysfs-elp_in.patch | 108 ++++++++++++++++++ ...ackbone_gw-refcount-on-queue_work-fa.patch | 45 ++++++++ ...ardif_neigh-refcount-on-queue_work-f.patch | 43 +++++++ ...revent-duplicated-gateway_node-entry.patch | 81 +++++++++++++ ...adv-Prevent-duplicated-nc_node-entry.patch | 90 +++++++++++++++ ...Prevent-duplicated-softif_vlan-entry.patch | 81 +++++++++++++ ...v-Prevent-duplicated-global-TT-entry.patch | 59 ++++++++++ ...-adv-Prevent-duplicated-tvlv-handler.patch | 59 ++++++++++ 12 files changed, 676 insertions(+), 1 deletion(-) create mode 100644 batman-adv/patches/0046-batman-adv-Avoid-probe-ELP-information-leak.patch create mode 100644 batman-adv/patches/0047-batman-adv-Fix-segfault-when-writing-to-throughput_o.patch create mode 100644 batman-adv/patches/0048-batman-adv-Fix-segfault-when-writing-to-sysfs-elp_in.patch create mode 100644 batman-adv/patches/0049-batman-adv-fix-backbone_gw-refcount-on-queue_work-fa.patch create mode 100644 batman-adv/patches/0050-batman-adv-fix-hardif_neigh-refcount-on-queue_work-f.patch create mode 100644 batman-adv/patches/0051-batman-adv-Prevent-duplicated-gateway_node-entry.patch create mode 100644 batman-adv/patches/0052-batman-adv-Prevent-duplicated-nc_node-entry.patch create mode 100644 batman-adv/patches/0053-batman-adv-Prevent-duplicated-softif_vlan-entry.patch create mode 100644 batman-adv/patches/0054-batman-adv-Prevent-duplicated-global-TT-entry.patch create mode 100644 batman-adv/patches/0055-batman-adv-Prevent-duplicated-tvlv-handler.patch diff --git a/batman-adv/Makefile b/batman-adv/Makefile index 0a63fa8..10d77c2 100644 --- a/batman-adv/Makefile +++ b/batman-adv/Makefile @@ -11,7 +11,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=batman-adv PKG_VERSION:=2016.5 -PKG_RELEASE:=9 +PKG_RELEASE:=10 PKG_MD5SUM:=6717a933a08dd2a01b00df30cb9f16a8 PKG_HASH:=d0a0fc90c4f410b57d043215e253bb0b855efa5edbe165d87c17bfdcfafd0db7 diff --git a/batman-adv/files/compat-hacks.h b/batman-adv/files/compat-hacks.h index ea7200c..1f1bdc2 100644 --- a/batman-adv/files/compat-hacks.h +++ b/batman-adv/files/compat-hacks.h @@ -192,6 +192,35 @@ static inline int batadv_nla_put_u64_64bit(struct sk_buff *skb, int attrtype, #endif /* < KERNEL_VERSION(4, 7, 0) */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(4, 13, 0) + +static inline void *batadv_skb_put(struct sk_buff *skb, unsigned int len) +{ + return (void *)skb_put(skb, len); +} +#define skb_put batadv_skb_put + +static inline void *skb_put_zero(struct sk_buff *skb, unsigned int len) +{ + void *tmp = skb_put(skb, len); + + memset(tmp, 0, len); + + return tmp; +} + +static inline void *skb_put_data(struct sk_buff *skb, const void *data, + unsigned int len) +{ + void *tmp = skb_put(skb, len); + + memcpy(tmp, data, len); + + return tmp; +} + +#endif /* < KERNEL_VERSION(4, 13, 0) */ + #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 10, 0) diff --git a/batman-adv/patches/0046-batman-adv-Avoid-probe-ELP-information-leak.patch b/batman-adv/patches/0046-batman-adv-Avoid-probe-ELP-information-leak.patch new file mode 100644 index 0000000..b219c5f --- /dev/null +++ b/batman-adv/patches/0046-batman-adv-Avoid-probe-ELP-information-leak.patch @@ -0,0 +1,35 @@ +From: Sven Eckelmann +Date: Fri, 31 Aug 2018 15:08:44 +0200 +Subject: [PATCH] batman-adv: Avoid probe ELP information leak + +The probe ELPs for WiFi interfaces are expanded to contain at least +BATADV_ELP_MIN_PROBE_SIZE bytes. This is usually a lot more than the +number of bytes which the template ELP packet requires. + +These extra padding bytes were not initialized and thus could contain data +which were previously stored at the same location. It is therefore required +to set it to some predefined or random values to avoid leaking private +information from the system transmitting these kind of packets. + +Fixes: bedcadfaa92b ("batman-adv: ELP - send unicast ELP packets for throughput sampling") +Signed-off-by: Sven Eckelmann +Acked-by: Antonio Quartulli + +Origin: upstream, https://git.open-mesh.org/batman-adv.git/commit/6c876e572f592c31132a55b5fb8427e168e5fb3c +--- + net/batman-adv/bat_v_elp.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/batman-adv/bat_v_elp.c b/net/batman-adv/bat_v_elp.c +index 06b2924f4cb7dde54bab97ad2d28aecd9b1a4ceb..e988a14f3eb01de1f52fe6dcaa91af898060140e 100644 +--- a/net/batman-adv/bat_v_elp.c ++++ b/net/batman-adv/bat_v_elp.c +@@ -227,7 +227,7 @@ batadv_v_elp_wifi_neigh_probe(struct batadv_hardif_neigh_node *neigh) + * the packet to be exactly of that size to make the link + * throughput estimation effective. + */ +- skb_put(skb, probe_len - hard_iface->bat_v.elp_skb->len); ++ skb_put_zero(skb, probe_len - hard_iface->bat_v.elp_skb->len); + + batadv_dbg(BATADV_DBG_BATMAN, bat_priv, + "Sending unicast (probe) ELP packet on interface %s to %pM\n", diff --git a/batman-adv/patches/0047-batman-adv-Fix-segfault-when-writing-to-throughput_o.patch b/batman-adv/patches/0047-batman-adv-Fix-segfault-when-writing-to-throughput_o.patch new file mode 100644 index 0000000..8594895 --- /dev/null +++ b/batman-adv/patches/0047-batman-adv-Fix-segfault-when-writing-to-throughput_o.patch @@ -0,0 +1,45 @@ +From: Sven Eckelmann +Date: Fri, 31 Aug 2018 16:46:47 +0200 +Subject: [PATCH] batman-adv: Fix segfault when writing to throughput_override + +The per hardif sysfs file "batman_adv/throughput_override" prints the +resulting change as info text when the users writes to this file. It uses +the helper function batadv_info to add it at the same time to the kernel +ring buffer and to the batman-adv debug log (when CONFIG_BATMAN_ADV_DEBUG +is enabled). + +The function batadv_info requires as first parameter the batman-adv softif +net_device. This parameter is then used to find the private buffer which +contains the debug log for this batman-adv interface. But +batadv_store_throughput_override used as first argument the slave +net_device. This slave device doesn't have the batadv_priv private data +which is access by batadv_info. + +Writing to this file with CONFIG_BATMAN_ADV_DEBUG enabled can either lead +to a segfault or to memory corruption. + +Fixes: c513176e4b7a ("batman-adv: add throughput override attribute to hard_ifaces") +Signed-off-by: Sven Eckelmann +Acked-by: Marek Lindner + +Origin: upstream, https://git.open-mesh.org/batman-adv.git/commit/ddf99b78e255530cbadc0f67656a549e19520280 +--- + net/batman-adv/sysfs.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/net/batman-adv/sysfs.c b/net/batman-adv/sysfs.c +index 17c844196eb26c9faf9fd543b88cd86cc1c2c029..ae22db3d6637dde2fcc238826a624ef2d6dbd8f5 100644 +--- a/net/batman-adv/sysfs.c ++++ b/net/batman-adv/sysfs.c +@@ -1078,8 +1078,9 @@ static ssize_t batadv_store_throughput_override(struct kobject *kobj, + if (old_tp_override == tp_override) + goto out; + +- batadv_info(net_dev, "%s: Changing from: %u.%u MBit to: %u.%u MBit\n", +- "throughput_override", ++ batadv_info(hard_iface->soft_iface, ++ "%s: %s: Changing from: %u.%u MBit to: %u.%u MBit\n", ++ "throughput_override", net_dev->name, + old_tp_override / 10, old_tp_override % 10, + tp_override / 10, tp_override % 10); + diff --git a/batman-adv/patches/0048-batman-adv-Fix-segfault-when-writing-to-sysfs-elp_in.patch b/batman-adv/patches/0048-batman-adv-Fix-segfault-when-writing-to-sysfs-elp_in.patch new file mode 100644 index 0000000..a77ab85 --- /dev/null +++ b/batman-adv/patches/0048-batman-adv-Fix-segfault-when-writing-to-sysfs-elp_in.patch @@ -0,0 +1,108 @@ +From: Sven Eckelmann +Date: Fri, 31 Aug 2018 16:56:29 +0200 +Subject: [PATCH] batman-adv: Fix segfault when writing to sysfs elp_interval + +The per hardif sysfs file "batman_adv/elp_interval" is using the generic +functions to store/show uint values. The helper __batadv_store_uint_attr +requires the softif net_device as parameter to print the resulting change +as info text when the users writes to this file. It uses the helper +function batadv_info to add it at the same time to the kernel ring buffer +and to the batman-adv debug log (when CONFIG_BATMAN_ADV_DEBUG is enabled). + +The function batadv_info requires as first parameter the batman-adv softif +net_device. This parameter is then used to find the private buffer which +contains the debug log for this batman-adv interface. But +batadv_store_throughput_override used as first argument the slave +net_device. This slave device doesn't have the batadv_priv private data +which is access by batadv_info. + +Writing to this file with CONFIG_BATMAN_ADV_DEBUG enabled can either lead +to a segfault or to memory corruption. + +Fixes: ec46535b8275 ("batman-adv: Add hard_iface specific sysfs wrapper macros for UINT") +Signed-off-by: Sven Eckelmann +Acked-by: Marek Lindner + +Origin: upstream, https://git.open-mesh.org/batman-adv.git/commit/848be9859b0109a6e428f92f21f2e660153b1c75 +--- + net/batman-adv/sysfs.c | 25 +++++++++++++++++-------- + 1 file changed, 17 insertions(+), 8 deletions(-) + +diff --git a/net/batman-adv/sysfs.c b/net/batman-adv/sysfs.c +index ae22db3d6637dde2fcc238826a624ef2d6dbd8f5..a4e6f158de26dea0e8e3fefd5b9aeec3dcd64457 100644 +--- a/net/batman-adv/sysfs.c ++++ b/net/batman-adv/sysfs.c +@@ -186,7 +186,8 @@ ssize_t batadv_store_##_name(struct kobject *kobj, \ + \ + return __batadv_store_uint_attr(buff, count, _min, _max, \ + _post_func, attr, \ +- &bat_priv->_var, net_dev); \ ++ &bat_priv->_var, net_dev, \ ++ NULL); \ + } + + #define BATADV_ATTR_SIF_SHOW_UINT(_name, _var) \ +@@ -260,7 +261,9 @@ ssize_t batadv_store_##_name(struct kobject *kobj, \ + \ + length = __batadv_store_uint_attr(buff, count, _min, _max, \ + _post_func, attr, \ +- &hard_iface->_var, net_dev); \ ++ &hard_iface->_var, \ ++ hard_iface->soft_iface, \ ++ net_dev); \ + \ + batadv_hardif_put(hard_iface); \ + return length; \ +@@ -354,10 +357,12 @@ __batadv_store_bool_attr(char *buff, size_t count, + + static int batadv_store_uint_attr(const char *buff, size_t count, + struct net_device *net_dev, ++ struct net_device *slave_dev, + const char *attr_name, + unsigned int min, unsigned int max, + atomic_t *attr) + { ++ char ifname[IFNAMSIZ + 3] = ""; + unsigned long uint_val; + int ret; + +@@ -383,8 +388,11 @@ static int batadv_store_uint_attr(const char *buff, size_t count, + if (atomic_read(attr) == uint_val) + return count; + +- batadv_info(net_dev, "%s: Changing from: %i to: %lu\n", +- attr_name, atomic_read(attr), uint_val); ++ if (slave_dev) ++ snprintf(ifname, sizeof(ifname), "%s: ", slave_dev->name); ++ ++ batadv_info(net_dev, "%s: %sChanging from: %i to: %lu\n", ++ attr_name, ifname, atomic_read(attr), uint_val); + + atomic_set(attr, uint_val); + return count; +@@ -395,12 +403,13 @@ static ssize_t __batadv_store_uint_attr(const char *buff, size_t count, + void (*post_func)(struct net_device *), + const struct attribute *attr, + atomic_t *attr_store, +- struct net_device *net_dev) ++ struct net_device *net_dev, ++ struct net_device *slave_dev) + { + int ret; + +- ret = batadv_store_uint_attr(buff, count, net_dev, attr->name, min, max, +- attr_store); ++ ret = batadv_store_uint_attr(buff, count, net_dev, slave_dev, ++ attr->name, min, max, attr_store); + if (post_func && ret) + post_func(net_dev); + +@@ -569,7 +578,7 @@ static ssize_t batadv_store_gw_sel_class(struct kobject *kobj, + return __batadv_store_uint_attr(buff, count, 1, BATADV_TQ_MAX_VALUE, + batadv_post_gw_reselect, attr, + &bat_priv->gw.sel_class, +- bat_priv->soft_iface); ++ bat_priv->soft_iface, NULL); + } + + static ssize_t batadv_show_gw_bwidth(struct kobject *kobj, diff --git a/batman-adv/patches/0049-batman-adv-fix-backbone_gw-refcount-on-queue_work-fa.patch b/batman-adv/patches/0049-batman-adv-fix-backbone_gw-refcount-on-queue_work-fa.patch new file mode 100644 index 0000000..b47371a --- /dev/null +++ b/batman-adv/patches/0049-batman-adv-fix-backbone_gw-refcount-on-queue_work-fa.patch @@ -0,0 +1,45 @@ +From: Marek Lindner +Date: Fri, 7 Sep 2018 05:45:54 +0800 +Subject: [PATCH] batman-adv: fix backbone_gw refcount on queue_work() failure + +The backbone_gw refcounter is to be decreased by the queued work and +currently is never decreased if the queue_work() call fails. +Fix by checking the queue_work() return value and decrease refcount +if necessary. + +Signed-off-by: Marek Lindner +Signed-off-by: Sven Eckelmann + +Origin: upstream, https://git.open-mesh.org/batman-adv.git/commit/24d83a50421c1c5d39cd9c015516a1a293ae8d0c +--- + net/batman-adv/bridge_loop_avoidance.c | 10 ++++++++-- + 1 file changed, 8 insertions(+), 2 deletions(-) + +diff --git a/net/batman-adv/bridge_loop_avoidance.c b/net/batman-adv/bridge_loop_avoidance.c +index aecf34503e95d9aa723449ddbf0bb3035336b878..258a74fd1c237fbf1b81dfc1c48720d8359b0ecc 100644 +--- a/net/batman-adv/bridge_loop_avoidance.c ++++ b/net/batman-adv/bridge_loop_avoidance.c +@@ -1767,6 +1767,7 @@ batadv_bla_loopdetect_check(struct batadv_priv *bat_priv, struct sk_buff *skb, + { + struct batadv_bla_backbone_gw *backbone_gw; + struct ethhdr *ethhdr; ++ bool ret; + + ethhdr = eth_hdr(skb); + +@@ -1790,8 +1791,13 @@ batadv_bla_loopdetect_check(struct batadv_priv *bat_priv, struct sk_buff *skb, + if (unlikely(!backbone_gw)) + return true; + +- queue_work(batadv_event_workqueue, &backbone_gw->report_work); +- /* backbone_gw is unreferenced in the report work function function */ ++ ret = queue_work(batadv_event_workqueue, &backbone_gw->report_work); ++ ++ /* backbone_gw is unreferenced in the report work function function ++ * if queue_work() call was successful ++ */ ++ if (!ret) ++ batadv_backbone_gw_put(backbone_gw); + + return true; + } diff --git a/batman-adv/patches/0050-batman-adv-fix-hardif_neigh-refcount-on-queue_work-f.patch b/batman-adv/patches/0050-batman-adv-fix-hardif_neigh-refcount-on-queue_work-f.patch new file mode 100644 index 0000000..02c28ba --- /dev/null +++ b/batman-adv/patches/0050-batman-adv-fix-hardif_neigh-refcount-on-queue_work-f.patch @@ -0,0 +1,43 @@ +From: Marek Lindner +Date: Fri, 7 Sep 2018 05:45:55 +0800 +Subject: [PATCH] batman-adv: fix hardif_neigh refcount on queue_work() failure + +The hardif_neigh refcounter is to be decreased by the queued work and +currently is never decreased if the queue_work() call fails. +Fix by checking the queue_work() return value and decrease refcount +if necessary. + +Signed-off-by: Marek Lindner +Signed-off-by: Sven Eckelmann + +Origin: upstream, https://git.open-mesh.org/batman-adv.git/commit/85100b602c127cecf1bcfd620d20eb867d685df2 +--- + net/batman-adv/bat_v_elp.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/net/batman-adv/bat_v_elp.c b/net/batman-adv/bat_v_elp.c +index e988a14f3eb01de1f52fe6dcaa91af898060140e..2ec0ecab0493ff88fdc01e55c8557de5b772e8bf 100644 +--- a/net/batman-adv/bat_v_elp.c ++++ b/net/batman-adv/bat_v_elp.c +@@ -254,6 +254,7 @@ static void batadv_v_elp_periodic_work(struct work_struct *work) + struct batadv_priv *bat_priv; + struct sk_buff *skb; + u32 elp_interval; ++ bool ret; + + bat_v = container_of(work, struct batadv_hard_iface_bat_v, elp_wq.work); + hard_iface = container_of(bat_v, struct batadv_hard_iface, bat_v); +@@ -315,8 +316,11 @@ static void batadv_v_elp_periodic_work(struct work_struct *work) + * may sleep and that is not allowed in an rcu protected + * context. Therefore schedule a task for that. + */ +- queue_work(batadv_event_workqueue, +- &hardif_neigh->bat_v.metric_work); ++ ret = queue_work(batadv_event_workqueue, ++ &hardif_neigh->bat_v.metric_work); ++ ++ if (!ret) ++ batadv_hardif_neigh_put(hardif_neigh); + } + rcu_read_unlock(); + diff --git a/batman-adv/patches/0051-batman-adv-Prevent-duplicated-gateway_node-entry.patch b/batman-adv/patches/0051-batman-adv-Prevent-duplicated-gateway_node-entry.patch new file mode 100644 index 0000000..5e8655f --- /dev/null +++ b/batman-adv/patches/0051-batman-adv-Prevent-duplicated-gateway_node-entry.patch @@ -0,0 +1,81 @@ +From: Sven Eckelmann +Date: Thu, 6 Sep 2018 14:35:24 +0200 +Subject: [PATCH] batman-adv: Prevent duplicated gateway_node entry + +The function batadv_gw_node_add is responsible for adding new gw_node to +the gateway_list. It is expecting that the caller already checked that +there is not already an entry with the same key or not. + +But the lock for the list is only held when the list is really modified. +This could lead to duplicated entries because another context could create +an entry with the same key between the check and the list manipulation. + +The check and the manipulation of the list must therefore be in the same +locked code section. + +Fixes: bc3538cabac5 ("batman-adv: adding gateway functionality") +Signed-off-by: Sven Eckelmann +Acked-by: Marek Lindner + +Origin: upstream, https://git.open-mesh.org/batman-adv.git/commit/69b3ca714eba608fe79a51ccd89ce7050ee0b770 +--- + net/batman-adv/gateway_client.c | 11 +++++++++-- + 1 file changed, 9 insertions(+), 2 deletions(-) + +diff --git a/net/batman-adv/gateway_client.c b/net/batman-adv/gateway_client.c +index f1fdf4e7f5c3ce7f20339dcee3b6e43290ea3b4e..a6f5a3969529745d6efa1d43a89440745e1926ad 100644 +--- 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 batadv_priv *bat_priv, + { + 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 batadv_priv *bat_priv, + gw_node->bandwidth_down = ntohl(gateway->bandwidth_down); + gw_node->bandwidth_up = ntohl(gateway->bandwidth_up); + +- spin_lock_bh(&bat_priv->gw.list_lock); + kref_get(&gw_node->refcount); + hlist_add_head_rcu(&gw_node->list, &bat_priv->gw.gateway_list); +- spin_unlock_bh(&bat_priv->gw.list_lock); + + batadv_dbg(BATADV_DBG_BATMAN, bat_priv, + "Found new gateway %pM -> gw bandwidth: %u.%u/%u.%u MBit\n", +@@ -405,11 +409,14 @@ void batadv_gw_node_update(struct batadv_priv *bat_priv, + { + struct batadv_gw_node *gw_node, *curr_gw = NULL; + ++ spin_lock_bh(&bat_priv->gw.list_lock); + gw_node = batadv_gw_node_get(bat_priv, orig_node); + if (!gw_node) { + batadv_gw_node_add(bat_priv, orig_node, gateway); ++ spin_unlock_bh(&bat_priv->gw.list_lock); + goto out; + } ++ spin_unlock_bh(&bat_priv->gw.list_lock); + + if ((gw_node->bandwidth_down == ntohl(gateway->bandwidth_down)) && + (gw_node->bandwidth_up == ntohl(gateway->bandwidth_up))) diff --git a/batman-adv/patches/0052-batman-adv-Prevent-duplicated-nc_node-entry.patch b/batman-adv/patches/0052-batman-adv-Prevent-duplicated-nc_node-entry.patch new file mode 100644 index 0000000..1d990f5 --- /dev/null +++ b/batman-adv/patches/0052-batman-adv-Prevent-duplicated-nc_node-entry.patch @@ -0,0 +1,90 @@ +From: Sven Eckelmann +Date: Thu, 6 Sep 2018 14:35:25 +0200 +Subject: [PATCH] batman-adv: Prevent duplicated nc_node entry + +The function batadv_nc_get_nc_node is responsible for adding new nc_nodes +to the in_coding_list and out_coding_list. It first checks whether the +entry already is in the list or not. If it is, then the creation of a new +entry is aborted. + +But the lock for the list is only held when the list is really modified. +This could lead to duplicated entries because another context could create +an entry with the same key between the check and the list manipulation. + +The check and the manipulation of the list must therefore be in the same +locked code section. + +Fixes: 3ed7ada3f0bb ("batman-adv: network coding - detect coding nodes and remove these after timeout") +Signed-off-by: Sven Eckelmann +Acked-by: Marek Lindner + +Origin: upstream, https://git.open-mesh.org/batman-adv.git/commit/bab8447ad1850b25188f9652c0c52f8e58acd656 +--- + net/batman-adv/network-coding.c | 41 ++++++++++++++++++--------------- + 1 file changed, 22 insertions(+), 19 deletions(-) + +diff --git a/net/batman-adv/network-coding.c b/net/batman-adv/network-coding.c +index ab5a3bf0765f36f2fe14ff4a91d43d905e08a1f3..3279f7f3b97fd56535071b857cebebd68a5b3484 100644 +--- a/net/batman-adv/network-coding.c ++++ b/net/batman-adv/network-coding.c +@@ -850,24 +850,6 @@ batadv_nc_get_nc_node(struct batadv_priv *bat_priv, + spinlock_t *lock; /* Used to lock list selected by "int in_coding" */ + struct list_head *list; + +- /* Check if nc_node is already added */ +- nc_node = batadv_nc_find_nc_node(orig_node, orig_neigh_node, in_coding); +- +- /* Node found */ +- if (nc_node) +- return nc_node; +- +- nc_node = kzalloc(sizeof(*nc_node), GFP_ATOMIC); +- if (!nc_node) +- return NULL; +- +- /* Initialize nc_node */ +- INIT_LIST_HEAD(&nc_node->list); +- kref_init(&nc_node->refcount); +- ether_addr_copy(nc_node->addr, orig_node->orig); +- kref_get(&orig_neigh_node->refcount); +- nc_node->orig_node = orig_neigh_node; +- + /* Select ingoing or outgoing coding node */ + if (in_coding) { + lock = &orig_neigh_node->in_coding_list_lock; +@@ -877,13 +859,34 @@ batadv_nc_get_nc_node(struct batadv_priv *bat_priv, + list = &orig_neigh_node->out_coding_list; + } + ++ spin_lock_bh(lock); ++ ++ /* Check if nc_node is already added */ ++ nc_node = batadv_nc_find_nc_node(orig_node, orig_neigh_node, in_coding); ++ ++ /* Node found */ ++ if (nc_node) ++ goto unlock; ++ ++ nc_node = kzalloc(sizeof(*nc_node), GFP_ATOMIC); ++ if (!nc_node) ++ goto unlock; ++ ++ /* Initialize nc_node */ ++ INIT_LIST_HEAD(&nc_node->list); ++ kref_init(&nc_node->refcount); ++ ether_addr_copy(nc_node->addr, orig_node->orig); ++ kref_get(&orig_neigh_node->refcount); ++ nc_node->orig_node = orig_neigh_node; ++ + batadv_dbg(BATADV_DBG_NC, bat_priv, "Adding nc_node %pM -> %pM\n", + nc_node->addr, nc_node->orig_node->orig); + + /* Add nc_node to orig_node */ +- spin_lock_bh(lock); + kref_get(&nc_node->refcount); + list_add_tail_rcu(&nc_node->list, list); ++ ++unlock: + spin_unlock_bh(lock); + + return nc_node; diff --git a/batman-adv/patches/0053-batman-adv-Prevent-duplicated-softif_vlan-entry.patch b/batman-adv/patches/0053-batman-adv-Prevent-duplicated-softif_vlan-entry.patch new file mode 100644 index 0000000..46a68cf --- /dev/null +++ b/batman-adv/patches/0053-batman-adv-Prevent-duplicated-softif_vlan-entry.patch @@ -0,0 +1,81 @@ +From: Sven Eckelmann +Date: Thu, 6 Sep 2018 14:35:26 +0200 +Subject: [PATCH] batman-adv: Prevent duplicated softif_vlan entry + +The function batadv_softif_vlan_get is responsible for adding new +softif_vlan to the softif_vlan_list. It first checks whether the entry +already is in the list or not. If it is, then the creation of a new entry +is aborted. + +But the lock for the list is only held when the list is really modified. +This could lead to duplicated entries because another context could create +an entry with the same key between the check and the list manipulation. + +The check and the manipulation of the list must therefore be in the same +locked code section. + +Fixes: 952cebb57518 ("batman-adv: add per VLAN interface attribute framework") +Signed-off-by: Sven Eckelmann + +Origin: upstream, https://git.open-mesh.org/batman-adv.git/commit/023d3f64207e8b6a6e6d0718d98e239c5545ef0c +--- + net/batman-adv/soft-interface.c | 27 +++++++++++++++++++-------- + 1 file changed, 19 insertions(+), 8 deletions(-) + +diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c +index 5da1a1c0f1efb5d95f31bc852b899f61e462feb1..ff797f32fb3bb81dafe1e7d3e9c6307e6a5aaff1 100644 +--- a/net/batman-adv/soft-interface.c ++++ b/net/batman-adv/soft-interface.c +@@ -587,15 +587,20 @@ int batadv_softif_create_vlan(struct batadv_priv *bat_priv, unsigned short vid) + struct batadv_softif_vlan *vlan; + int err; + ++ spin_lock_bh(&bat_priv->softif_vlan_list_lock); ++ + vlan = batadv_softif_vlan_get(bat_priv, vid); + if (vlan) { + batadv_softif_vlan_put(vlan); ++ spin_unlock_bh(&bat_priv->softif_vlan_list_lock); + return -EEXIST; + } + + vlan = kzalloc(sizeof(*vlan), GFP_ATOMIC); +- if (!vlan) ++ if (!vlan) { ++ spin_unlock_bh(&bat_priv->softif_vlan_list_lock); + return -ENOMEM; ++ } + + vlan->bat_priv = bat_priv; + vlan->vid = vid; +@@ -603,17 +608,23 @@ int batadv_softif_create_vlan(struct batadv_priv *bat_priv, unsigned short vid) + + atomic_set(&vlan->ap_isolation, 0); + +- err = batadv_sysfs_add_vlan(bat_priv->soft_iface, vlan); +- if (err) { +- kfree(vlan); +- return err; +- } +- +- spin_lock_bh(&bat_priv->softif_vlan_list_lock); + kref_get(&vlan->refcount); + hlist_add_head_rcu(&vlan->list, &bat_priv->softif_vlan_list); + spin_unlock_bh(&bat_priv->softif_vlan_list_lock); + ++ /* batadv_sysfs_add_vlan cannot be in the spinlock section due to the ++ * sleeping behavior of the sysfs functions and the fs_reclaim lock ++ */ ++ err = batadv_sysfs_add_vlan(bat_priv->soft_iface, vlan); ++ if (err) { ++ /* ref for the function */ ++ batadv_softif_vlan_put(vlan); ++ ++ /* ref for the list */ ++ batadv_softif_vlan_put(vlan); ++ return err; ++ } ++ + /* add a new TT local entry. This one will be marked with the NOPURGE + * flag + */ diff --git a/batman-adv/patches/0054-batman-adv-Prevent-duplicated-global-TT-entry.patch b/batman-adv/patches/0054-batman-adv-Prevent-duplicated-global-TT-entry.patch new file mode 100644 index 0000000..8fce2bf --- /dev/null +++ b/batman-adv/patches/0054-batman-adv-Prevent-duplicated-global-TT-entry.patch @@ -0,0 +1,59 @@ +From: Sven Eckelmann +Date: Thu, 6 Sep 2018 14:35:27 +0200 +Subject: [PATCH] batman-adv: Prevent duplicated global TT entry + +The function batadv_tt_global_orig_entry_add is responsible for adding new +tt_orig_list_entry to the orig_list. It first checks whether the entry +already is in the list or not. If it is, then the creation of a new entry +is aborted. + +But the lock for the list is only held when the list is really modified. +This could lead to duplicated entries because another context could create +an entry with the same key between the check and the list manipulation. + +The check and the manipulation of the list must therefore be in the same +locked code section. + +Fixes: c5eb5bb30321 ("batman-adv: add reference counting for type batadv_tt_orig_list_entry") +Signed-off-by: Sven Eckelmann +Acked-by: Marek Lindner + +Origin: upstream, https://git.open-mesh.org/batman-adv.git/commit/79097255a1a3e1bd1949be309af941181fbc7b36 +--- + net/batman-adv/translation-table.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c +index 143a00f90d1d925aad7113f897d06f435f28dcd8..b32853cbab028f0a052492545bb803efdcdb0ff3 100644 +--- a/net/batman-adv/translation-table.c ++++ b/net/batman-adv/translation-table.c +@@ -1603,6 +1603,8 @@ batadv_tt_global_orig_entry_add(struct batadv_tt_global_entry *tt_global, + { + struct batadv_tt_orig_list_entry *orig_entry; + ++ spin_lock_bh(&tt_global->list_lock); ++ + orig_entry = batadv_tt_global_orig_entry_find(tt_global, orig_node); + if (orig_entry) { + /* refresh the ttvn: the current value could be a bogus one that +@@ -1625,11 +1627,9 @@ batadv_tt_global_orig_entry_add(struct batadv_tt_global_entry *tt_global, + orig_entry->flags = flags; + kref_init(&orig_entry->refcount); + +- spin_lock_bh(&tt_global->list_lock); + kref_get(&orig_entry->refcount); + hlist_add_head_rcu(&orig_entry->list, + &tt_global->orig_list); +- spin_unlock_bh(&tt_global->list_lock); + atomic_inc(&tt_global->orig_list_count); + + sync_flags: +@@ -1637,6 +1637,8 @@ sync_flags: + out: + if (orig_entry) + batadv_tt_orig_list_entry_put(orig_entry); ++ ++ spin_unlock_bh(&tt_global->list_lock); + } + + /** diff --git a/batman-adv/patches/0055-batman-adv-Prevent-duplicated-tvlv-handler.patch b/batman-adv/patches/0055-batman-adv-Prevent-duplicated-tvlv-handler.patch new file mode 100644 index 0000000..ef9e9fe --- /dev/null +++ b/batman-adv/patches/0055-batman-adv-Prevent-duplicated-tvlv-handler.patch @@ -0,0 +1,59 @@ +From: Sven Eckelmann +Date: Thu, 6 Sep 2018 14:35:28 +0200 +Subject: [PATCH] batman-adv: Prevent duplicated tvlv handler + +The function batadv_tvlv_handler_register is responsible for adding new +tvlv_handler to the handler_list. It first checks whether the entry +already is in the list or not. If it is, then the creation of a new entry +is aborted. + +But the lock for the list is only held when the list is really modified. +This could lead to duplicated entries because another context could create +an entry with the same key between the check and the list manipulation. + +The check and the manipulation of the list must therefore be in the same +locked code section. + +Fixes: 0b6aa0d43767 ("batman-adv: tvlv - basic infrastructure") +Signed-off-by: Sven Eckelmann +Acked-by: Marek Lindner + +Origin: upstream, https://git.open-mesh.org/batman-adv.git/commit/acabad79e01740525cf4ff8ce6e9a210b683d420 +--- + net/batman-adv/tvlv.c | 8 ++++++-- + 1 file changed, 6 insertions(+), 2 deletions(-) + +diff --git a/net/batman-adv/tvlv.c b/net/batman-adv/tvlv.c +index a783420356ae0cd4a6273b3b7a04781242e37a82..1eccc49a793004db82346f9dc3be7fcc2386417b 100644 +--- a/net/batman-adv/tvlv.c ++++ b/net/batman-adv/tvlv.c +@@ -528,15 +528,20 @@ void batadv_tvlv_handler_register(struct batadv_priv *bat_priv, + { + struct batadv_tvlv_handler *tvlv_handler; + ++ spin_lock_bh(&bat_priv->tvlv.handler_list_lock); ++ + tvlv_handler = batadv_tvlv_handler_get(bat_priv, type, version); + if (tvlv_handler) { ++ spin_unlock_bh(&bat_priv->tvlv.handler_list_lock); + batadv_tvlv_handler_put(tvlv_handler); + return; + } + + tvlv_handler = kzalloc(sizeof(*tvlv_handler), GFP_ATOMIC); +- if (!tvlv_handler) ++ if (!tvlv_handler) { ++ spin_unlock_bh(&bat_priv->tvlv.handler_list_lock); + return; ++ } + + tvlv_handler->ogm_handler = optr; + tvlv_handler->unicast_handler = uptr; +@@ -546,7 +551,6 @@ void batadv_tvlv_handler_register(struct batadv_priv *bat_priv, + kref_init(&tvlv_handler->refcount); + INIT_HLIST_NODE(&tvlv_handler->list); + +- spin_lock_bh(&bat_priv->tvlv.handler_list_lock); + kref_get(&tvlv_handler->refcount); + hlist_add_head_rcu(&tvlv_handler->list, &bat_priv->tvlv.handler_list); + spin_unlock_bh(&bat_priv->tvlv.handler_list_lock);