mirror of
https://git.openwrt.org/feed/routing.git
synced 2024-06-18 05:03:57 +02:00
73 lines
2.8 KiB
Diff
73 lines
2.8 KiB
Diff
From: Sven Eckelmann <sven@narfation.org>
|
|
Date: Wed, 9 May 2018 21:07:40 +0200
|
|
Subject: batman-adv: Avoid race in TT TVLV allocator helper
|
|
|
|
The functions batadv_tt_prepare_tvlv_local_data and
|
|
batadv_tt_prepare_tvlv_global_data are responsible for preparing a buffer
|
|
which can be used to store the TVLV container for TT and add the VLAN
|
|
information to it.
|
|
|
|
This will be done in three phases:
|
|
|
|
1. count the number of VLANs and their entries
|
|
2. allocate the buffer using the counters from the previous step and limits
|
|
from the caller (parameter tt_len)
|
|
3. insert the VLAN information to the buffer
|
|
|
|
The step 1 and 3 operate on a list which contains the VLANs. The access to
|
|
these lists must be protected with an appropriate lock or otherwise they
|
|
might operate on on different entries. This could for example happen when
|
|
another context is adding VLAN entries to this list.
|
|
|
|
This could lead to a buffer overflow in these functions when enough entries
|
|
were added between step 1 and 3 to the VLAN lists that the buffer room for
|
|
the entries (*tt_change) is smaller then the now required extra buffer for
|
|
new VLAN entries.
|
|
|
|
Fixes: 21a57f6e7a3b ("batman-adv: make the TT CRC logic VLAN specific")
|
|
Signed-off-by: Sven Eckelmann <sven@narfation.org>
|
|
Acked-by: Antonio Quartulli <a@unstable.cc>
|
|
|
|
Origin: upstream, https://git.open-mesh.org/batman-adv.git/commit/286be89a33497ba9000aa5c2960f1f4114953522
|
|
|
|
diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c
|
|
index 91b9a0aaaa2e6fe59b5e4ea2e57b7be375618059..2511adb79936782c96ed397265418421b69f617d 100644
|
|
--- a/net/batman-adv/translation-table.c
|
|
+++ b/net/batman-adv/translation-table.c
|
|
@@ -862,7 +862,7 @@ batadv_tt_prepare_tvlv_global_data(struct batadv_orig_node *orig_node,
|
|
struct batadv_orig_node_vlan *vlan;
|
|
u8 *tt_change_ptr;
|
|
|
|
- rcu_read_lock();
|
|
+ spin_lock_bh(&orig_node->vlan_list_lock);
|
|
hlist_for_each_entry_rcu(vlan, &orig_node->vlan_list, list) {
|
|
num_vlan++;
|
|
num_entries += atomic_read(&vlan->tt.num_entries);
|
|
@@ -900,7 +900,7 @@ batadv_tt_prepare_tvlv_global_data(struct batadv_orig_node *orig_node,
|
|
*tt_change = (struct batadv_tvlv_tt_change *)tt_change_ptr;
|
|
|
|
out:
|
|
- rcu_read_unlock();
|
|
+ spin_unlock_bh(&orig_node->vlan_list_lock);
|
|
return tvlv_len;
|
|
}
|
|
|
|
@@ -936,7 +936,7 @@ batadv_tt_prepare_tvlv_local_data(struct batadv_priv *bat_priv,
|
|
u8 *tt_change_ptr;
|
|
int change_offset;
|
|
|
|
- rcu_read_lock();
|
|
+ spin_lock_bh(&bat_priv->softif_vlan_list_lock);
|
|
hlist_for_each_entry_rcu(vlan, &bat_priv->softif_vlan_list, list) {
|
|
num_vlan++;
|
|
num_entries += atomic_read(&vlan->tt.num_entries);
|
|
@@ -974,7 +974,7 @@ batadv_tt_prepare_tvlv_local_data(struct batadv_priv *bat_priv,
|
|
*tt_change = (struct batadv_tvlv_tt_change *)tt_change_ptr;
|
|
|
|
out:
|
|
- rcu_read_unlock();
|
|
+ spin_unlock_bh(&bat_priv->softif_vlan_list_lock);
|
|
return tvlv_len;
|
|
}
|
|
|