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

Commit 95a428f3 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:

====================
Included changes:
- prevent DAT from replying on behalf of local clients and confuse L2
  bridges
- fix crash on double list removal of TT objects (tt_local_entry)
- fix crash due to missing NULL checks
- initialize bw values for new GWs objects to prevent memory leak
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents d1163e91 27a4d5ef
Loading
Loading
Loading
Loading
+13 −5
Original line number Original line Diff line number Diff line
@@ -1138,6 +1138,9 @@ void batadv_dat_snoop_outgoing_arp_reply(struct batadv_priv *bat_priv,
 * @bat_priv: the bat priv with all the soft interface information
 * @bat_priv: the bat priv with all the soft interface information
 * @skb: packet to check
 * @skb: packet to check
 * @hdr_size: size of the encapsulation header
 * @hdr_size: size of the encapsulation header
 *
 * Returns true if the packet was snooped and consumed by DAT. False if the
 * packet has to be delivered to the interface
 */
 */
bool batadv_dat_snoop_incoming_arp_reply(struct batadv_priv *bat_priv,
bool batadv_dat_snoop_incoming_arp_reply(struct batadv_priv *bat_priv,
					 struct sk_buff *skb, int hdr_size)
					 struct sk_buff *skb, int hdr_size)
@@ -1145,7 +1148,7 @@ bool batadv_dat_snoop_incoming_arp_reply(struct batadv_priv *bat_priv,
	uint16_t type;
	uint16_t type;
	__be32 ip_src, ip_dst;
	__be32 ip_src, ip_dst;
	uint8_t *hw_src, *hw_dst;
	uint8_t *hw_src, *hw_dst;
	bool ret = false;
	bool dropped = false;
	unsigned short vid;
	unsigned short vid;


	if (!atomic_read(&bat_priv->distributed_arp_table))
	if (!atomic_read(&bat_priv->distributed_arp_table))
@@ -1174,12 +1177,17 @@ bool batadv_dat_snoop_incoming_arp_reply(struct batadv_priv *bat_priv,
	/* if this REPLY is directed to a client of mine, let's deliver the
	/* if this REPLY is directed to a client of mine, let's deliver the
	 * packet to the interface
	 * packet to the interface
	 */
	 */
	ret = !batadv_is_my_client(bat_priv, hw_dst, vid);
	dropped = !batadv_is_my_client(bat_priv, hw_dst, vid);

	/* if this REPLY is sent on behalf of a client of mine, let's drop the
	 * packet because the client will reply by itself
	 */
	dropped |= batadv_is_my_client(bat_priv, hw_src, vid);
out:
out:
	if (ret)
	if (dropped)
		kfree_skb(skb);
		kfree_skb(skb);
	/* if ret == false -> packet has to be delivered to the interface */
	/* if dropped == false -> deliver to the interface */
	return ret;
	return dropped;
}
}


/**
/**
+2 −0
Original line number Original line Diff line number Diff line
@@ -439,6 +439,8 @@ static void batadv_gw_node_add(struct batadv_priv *bat_priv,


	INIT_HLIST_NODE(&gw_node->list);
	INIT_HLIST_NODE(&gw_node->list);
	gw_node->orig_node = orig_node;
	gw_node->orig_node = orig_node;
	gw_node->bandwidth_down = ntohl(gateway->bandwidth_down);
	gw_node->bandwidth_up = ntohl(gateway->bandwidth_up);
	atomic_set(&gw_node->refcount, 1);
	atomic_set(&gw_node->refcount, 1);


	spin_lock_bh(&bat_priv->gw.list_lock);
	spin_lock_bh(&bat_priv->gw.list_lock);
+3 −0
Original line number Original line Diff line number Diff line
@@ -479,6 +479,9 @@ void batadv_interface_rx(struct net_device *soft_iface,
 */
 */
void batadv_softif_vlan_free_ref(struct batadv_softif_vlan *vlan)
void batadv_softif_vlan_free_ref(struct batadv_softif_vlan *vlan)
{
{
	if (!vlan)
		return;

	if (atomic_dec_and_test(&vlan->refcount)) {
	if (atomic_dec_and_test(&vlan->refcount)) {
		spin_lock_bh(&vlan->bat_priv->softif_vlan_list_lock);
		spin_lock_bh(&vlan->bat_priv->softif_vlan_list_lock);
		hlist_del_rcu(&vlan->list);
		hlist_del_rcu(&vlan->list);
+24 −5
Original line number Original line Diff line number Diff line
@@ -594,6 +594,9 @@ bool batadv_tt_local_add(struct net_device *soft_iface, const uint8_t *addr,


	/* increase the refcounter of the related vlan */
	/* increase the refcounter of the related vlan */
	vlan = batadv_softif_vlan_get(bat_priv, vid);
	vlan = batadv_softif_vlan_get(bat_priv, vid);
	if (WARN(!vlan, "adding TT local entry %pM to non-existent VLAN %d",
		 addr, BATADV_PRINT_VID(vid)))
		goto out;


	batadv_dbg(BATADV_DBG_TT, bat_priv,
	batadv_dbg(BATADV_DBG_TT, bat_priv,
		   "Creating new local tt entry: %pM (vid: %d, ttvn: %d)\n",
		   "Creating new local tt entry: %pM (vid: %d, ttvn: %d)\n",
@@ -1034,6 +1037,7 @@ uint16_t batadv_tt_local_remove(struct batadv_priv *bat_priv,
	struct batadv_tt_local_entry *tt_local_entry;
	struct batadv_tt_local_entry *tt_local_entry;
	uint16_t flags, curr_flags = BATADV_NO_FLAGS;
	uint16_t flags, curr_flags = BATADV_NO_FLAGS;
	struct batadv_softif_vlan *vlan;
	struct batadv_softif_vlan *vlan;
	void *tt_entry_exists;


	tt_local_entry = batadv_tt_local_hash_find(bat_priv, addr, vid);
	tt_local_entry = batadv_tt_local_hash_find(bat_priv, addr, vid);
	if (!tt_local_entry)
	if (!tt_local_entry)
@@ -1061,11 +1065,22 @@ uint16_t batadv_tt_local_remove(struct batadv_priv *bat_priv,
	 * immediately purge it
	 * immediately purge it
	 */
	 */
	batadv_tt_local_event(bat_priv, tt_local_entry, BATADV_TT_CLIENT_DEL);
	batadv_tt_local_event(bat_priv, tt_local_entry, BATADV_TT_CLIENT_DEL);
	hlist_del_rcu(&tt_local_entry->common.hash_entry);

	tt_entry_exists = batadv_hash_remove(bat_priv->tt.local_hash,
					     batadv_compare_tt,
					     batadv_choose_tt,
					     &tt_local_entry->common);
	if (!tt_entry_exists)
		goto out;

	/* extra call to free the local tt entry */
	batadv_tt_local_entry_free_ref(tt_local_entry);
	batadv_tt_local_entry_free_ref(tt_local_entry);


	/* decrease the reference held for this vlan */
	/* decrease the reference held for this vlan */
	vlan = batadv_softif_vlan_get(bat_priv, vid);
	vlan = batadv_softif_vlan_get(bat_priv, vid);
	if (!vlan)
		goto out;

	batadv_softif_vlan_free_ref(vlan);
	batadv_softif_vlan_free_ref(vlan);
	batadv_softif_vlan_free_ref(vlan);
	batadv_softif_vlan_free_ref(vlan);


@@ -1166,8 +1181,10 @@ static void batadv_tt_local_table_free(struct batadv_priv *bat_priv)
			/* decrease the reference held for this vlan */
			/* decrease the reference held for this vlan */
			vlan = batadv_softif_vlan_get(bat_priv,
			vlan = batadv_softif_vlan_get(bat_priv,
						      tt_common_entry->vid);
						      tt_common_entry->vid);
			if (vlan) {
				batadv_softif_vlan_free_ref(vlan);
				batadv_softif_vlan_free_ref(vlan);
				batadv_softif_vlan_free_ref(vlan);
				batadv_softif_vlan_free_ref(vlan);
			}


			batadv_tt_local_entry_free_ref(tt_local);
			batadv_tt_local_entry_free_ref(tt_local);
		}
		}
@@ -3207,8 +3224,10 @@ static void batadv_tt_local_purge_pending_clients(struct batadv_priv *bat_priv)


			/* decrease the reference held for this vlan */
			/* decrease the reference held for this vlan */
			vlan = batadv_softif_vlan_get(bat_priv, tt_common->vid);
			vlan = batadv_softif_vlan_get(bat_priv, tt_common->vid);
			if (vlan) {
				batadv_softif_vlan_free_ref(vlan);
				batadv_softif_vlan_free_ref(vlan);
				batadv_softif_vlan_free_ref(vlan);
				batadv_softif_vlan_free_ref(vlan);
			}


			batadv_tt_local_entry_free_ref(tt_local);
			batadv_tt_local_entry_free_ref(tt_local);
		}
		}