Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 29d1441d authored by David S. Miller's avatar David S. Miller
Browse files

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: default avatarDavid S. Miller <davem@davemloft.net>
parents a97eb33f 1bc4e2b0
Loading
Loading
Loading
Loading
+4 −3
Original line number Diff line number Diff line
@@ -527,10 +527,11 @@ void batadv_gw_node_update(struct batadv_priv *bat_priv,
		 * gets dereferenced.
		 */
		spin_lock_bh(&bat_priv->gw.list_lock);
		if (!hlist_unhashed(&gw_node->list)) {
			hlist_del_init_rcu(&gw_node->list);
		spin_unlock_bh(&bat_priv->gw.list_lock);

			batadv_gw_node_free_ref(gw_node);
		}
		spin_unlock_bh(&bat_priv->gw.list_lock);

		curr_gw = batadv_gw_get_selected_gw_node(bat_priv);
		if (gw_node == curr_gw)
+25 −0
Original line number Diff line number Diff line
@@ -75,6 +75,28 @@ batadv_hardif_get_by_netdev(const struct net_device *net_dev)
	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;
+4 −2
Original line number Diff line number Diff line
@@ -303,10 +303,12 @@ 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);
		if (!hlist_unhashed(&vlan->list)) {
			hlist_del_init_rcu(&vlan->list);
		spin_unlock_bh(&orig_node->vlan_list_lock);
			batadv_orig_node_vlan_free_ref(vlan);
		}
		spin_unlock_bh(&orig_node->vlan_list_lock);
	}

	batadv_orig_node_vlan_free_ref(vlan);
}