aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSven Eckelmann <sven@narfation.org>2018-05-09 15:07:40 -0400
committerSimon Wunderlich <sw@simonwunderlich.de>2018-05-10 10:08:54 -0400
commit8ba0f9bd3bdea1058c2b2676bec7905724418e40 (patch)
tree3666991dea22d6dc49d10eec987d9668fcf9f0ae
parent65cc02a8e1d4449daedf3a84e9dfdda2e44a5d97 (diff)
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: 7ea7b4a14275 ("batman-adv: make the TT CRC logic VLAN specific") Signed-off-by: Sven Eckelmann <sven@narfation.org> Acked-by: Antonio Quartulli <a@unstable.cc> Signed-off-by: Simon Wunderlich <sw@simonwunderlich.de>
-rw-r--r--net/batman-adv/translation-table.c8
1 files changed, 4 insertions, 4 deletions
diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c
index 0225616d5771..7fa3a0a0524a 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,
862 struct batadv_orig_node_vlan *vlan; 862 struct batadv_orig_node_vlan *vlan;
863 u8 *tt_change_ptr; 863 u8 *tt_change_ptr;
864 864
865 rcu_read_lock(); 865 spin_lock_bh(&orig_node->vlan_list_lock);
866 hlist_for_each_entry_rcu(vlan, &orig_node->vlan_list, list) { 866 hlist_for_each_entry_rcu(vlan, &orig_node->vlan_list, list) {
867 num_vlan++; 867 num_vlan++;
868 num_entries += atomic_read(&vlan->tt.num_entries); 868 num_entries += atomic_read(&vlan->tt.num_entries);
@@ -900,7 +900,7 @@ batadv_tt_prepare_tvlv_global_data(struct batadv_orig_node *orig_node,
900 *tt_change = (struct batadv_tvlv_tt_change *)tt_change_ptr; 900 *tt_change = (struct batadv_tvlv_tt_change *)tt_change_ptr;
901 901
902out: 902out:
903 rcu_read_unlock(); 903 spin_unlock_bh(&orig_node->vlan_list_lock);
904 return tvlv_len; 904 return tvlv_len;
905} 905}
906 906
@@ -936,7 +936,7 @@ batadv_tt_prepare_tvlv_local_data(struct batadv_priv *bat_priv,
936 u8 *tt_change_ptr; 936 u8 *tt_change_ptr;
937 int change_offset; 937 int change_offset;
938 938
939 rcu_read_lock(); 939 spin_lock_bh(&bat_priv->softif_vlan_list_lock);
940 hlist_for_each_entry_rcu(vlan, &bat_priv->softif_vlan_list, list) { 940 hlist_for_each_entry_rcu(vlan, &bat_priv->softif_vlan_list, list) {
941 num_vlan++; 941 num_vlan++;
942 num_entries += atomic_read(&vlan->tt.num_entries); 942 num_entries += atomic_read(&vlan->tt.num_entries);
@@ -974,7 +974,7 @@ batadv_tt_prepare_tvlv_local_data(struct batadv_priv *bat_priv,
974 *tt_change = (struct batadv_tvlv_tt_change *)tt_change_ptr; 974 *tt_change = (struct batadv_tvlv_tt_change *)tt_change_ptr;
975 975
976out: 976out:
977 rcu_read_unlock(); 977 spin_unlock_bh(&bat_priv->softif_vlan_list_lock);
978 return tvlv_len; 978 return tvlv_len;
979} 979}
980 980