Two of the fixes included in this patchset prevent wrong memory

access - it was triggered when removing an object from a list
 after it was already free'd due to bad reference counting.
 This misbehaviour existed for both the gw_node and the
 orig_node_vlan object and has been fixed by Sven Eckelmann.
 
 The last patch fixes our interface feasibility check and prevents
 it from looping indefinitely when two net_device objects
 reference each other via iflink index (i.e. veth pair), by
 Andrew Lunn
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v2
 
 iQIcBAABCAAGBQJWwy9MAAoJENpFlCjNi1MRu+cQAMF7zYIlWggCWUEqaEIId4qi
 daGly3DNrXWH8FJta+NR399xXlTXNoyS8uZYt9YUZrXlwXDbDNBHJ8Jcmc5sslZr
 /06os5KUvNLlasup1GLBbynKUCTBSjVyo3DBwVCsiCL/iHdN1tFZXg3c2ET2U7Tk
 4bFZO4h1JkpwCYeCjCJQSbPrjnAXYdxV01iarDJZgAoc290f92Ob4mTuTrQr1Vzi
 EH2fyrd3m/qmRb2YBj7jNdVeD2Q4XyMKY4vHHeBq9JR/kwINwUg38+gnvcwK+KeD
 VJilETdC686ZJKBSVvECQZqeXr4HaCINFNuepZLsg128IQ2ZjqPYC1yTq/qc1VF+
 YGCunXhbbNgxeE1+QgXssgRAiUBx43m2osQegpHkyCzK8GPbv1gRIbTYaHgmqa4A
 Pn6WHdV2kcfGRFNOASST5+eWPe9ol8RvAbXT0yD2+6CNz6aijfbGITUTlB24X+f+
 6CsS3uCBsH8FI3hqjgULTqcyF14QbnLZ9AnkxYwt8B0Ge62LEfdwuXAh96mIhfyf
 cGi7DBnHAYapOPzz0jSBhW5myiPOioNLJfzokZrBq+RuRBYUIUvzGmz8QJQpy/GO
 EdnMOE/uWeZeSCsAGTE00pjqfHliK/vu4Wh0puGFWTQGCBbKWP5p4eNqRh4p+2GC
 Sg1f1EKDt2PRw9aZHNHm
 =CvI3
 -----END PGP SIGNATURE-----

Merge tag 'batman-adv-fix-for-davem' of git://git.open-mesh.org/linux-merge

Antonio Quartulli says:

====================
Two of the fixes included in this patchset prevent wrong memory
access - it was triggered when removing an object from a list
after it was already free'd due to bad reference counting.
This misbehaviour existed for both the gw_node and the
orig_node_vlan object and has been fixed by Sven Eckelmann.

The last patch fixes our interface feasibility check and prevents
it from looping indefinitely when two net_device objects
reference each other via iflink index (i.e. veth pair), by
Andrew Lunn
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
David S. Miller 2016-02-19 15:35:29 -05:00
commit 29d1441dfc
3 changed files with 33 additions and 5 deletions

View File

@ -527,11 +527,12 @@ void batadv_gw_node_update(struct batadv_priv *bat_priv,
* gets dereferenced.
*/
spin_lock_bh(&bat_priv->gw.list_lock);
hlist_del_init_rcu(&gw_node->list);
if (!hlist_unhashed(&gw_node->list)) {
hlist_del_init_rcu(&gw_node->list);
batadv_gw_node_free_ref(gw_node);
}
spin_unlock_bh(&bat_priv->gw.list_lock);
batadv_gw_node_free_ref(gw_node);
curr_gw = batadv_gw_get_selected_gw_node(bat_priv);
if (gw_node == curr_gw)
batadv_gw_reselect(bat_priv);

View File

@ -75,6 +75,28 @@ out:
return hard_iface;
}
/**
* batadv_mutual_parents - check if two devices are each others parent
* @dev1: 1st net_device
* @dev2: 2nd net_device
*
* veth devices come in pairs and each is the parent of the other!
*
* Return: true if the devices are each others parent, otherwise false
*/
static bool batadv_mutual_parents(const struct net_device *dev1,
const struct net_device *dev2)
{
int dev1_parent_iflink = dev_get_iflink(dev1);
int dev2_parent_iflink = dev_get_iflink(dev2);
if (!dev1_parent_iflink || !dev2_parent_iflink)
return false;
return (dev1_parent_iflink == dev2->ifindex) &&
(dev2_parent_iflink == dev1->ifindex);
}
/**
* batadv_is_on_batman_iface - check if a device is a batman iface descendant
* @net_dev: the device to check
@ -108,6 +130,9 @@ static bool batadv_is_on_batman_iface(const struct net_device *net_dev)
if (WARN(!parent_dev, "Cannot find parent device"))
return false;
if (batadv_mutual_parents(net_dev, parent_dev))
return false;
ret = batadv_is_on_batman_iface(parent_dev);
return ret;

View File

@ -303,9 +303,11 @@ static void batadv_tt_global_size_mod(struct batadv_orig_node *orig_node,
if (atomic_add_return(v, &vlan->tt.num_entries) == 0) {
spin_lock_bh(&orig_node->vlan_list_lock);
hlist_del_init_rcu(&vlan->list);
if (!hlist_unhashed(&vlan->list)) {
hlist_del_init_rcu(&vlan->list);
batadv_orig_node_vlan_free_ref(vlan);
}
spin_unlock_bh(&orig_node->vlan_list_lock);
batadv_orig_node_vlan_free_ref(vlan);
}
batadv_orig_node_vlan_free_ref(vlan);