mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-10 06:49:29 -04:00
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: David S. Miller <davem@davemloft.net>
This commit is contained in:
@@ -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
|
||||
* @skb: packet to check
|
||||
* @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,
|
||||
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;
|
||||
__be32 ip_src, ip_dst;
|
||||
uint8_t *hw_src, *hw_dst;
|
||||
bool ret = false;
|
||||
bool dropped = false;
|
||||
unsigned short vid;
|
||||
|
||||
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
|
||||
* 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:
|
||||
if (ret)
|
||||
if (dropped)
|
||||
kfree_skb(skb);
|
||||
/* if ret == false -> packet has to be delivered to the interface */
|
||||
return ret;
|
||||
/* if dropped == false -> deliver to the interface */
|
||||
return dropped;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -439,6 +439,8 @@ static void batadv_gw_node_add(struct batadv_priv *bat_priv,
|
||||
|
||||
INIT_HLIST_NODE(&gw_node->list);
|
||||
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);
|
||||
|
||||
spin_lock_bh(&bat_priv->gw.list_lock);
|
||||
|
||||
@@ -479,6 +479,9 @@ void batadv_interface_rx(struct net_device *soft_iface,
|
||||
*/
|
||||
void batadv_softif_vlan_free_ref(struct batadv_softif_vlan *vlan)
|
||||
{
|
||||
if (!vlan)
|
||||
return;
|
||||
|
||||
if (atomic_dec_and_test(&vlan->refcount)) {
|
||||
spin_lock_bh(&vlan->bat_priv->softif_vlan_list_lock);
|
||||
hlist_del_rcu(&vlan->list);
|
||||
|
||||
@@ -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 */
|
||||
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,
|
||||
"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;
|
||||
uint16_t flags, curr_flags = BATADV_NO_FLAGS;
|
||||
struct batadv_softif_vlan *vlan;
|
||||
void *tt_entry_exists;
|
||||
|
||||
tt_local_entry = batadv_tt_local_hash_find(bat_priv, addr, vid);
|
||||
if (!tt_local_entry)
|
||||
@@ -1061,11 +1065,22 @@ uint16_t batadv_tt_local_remove(struct batadv_priv *bat_priv,
|
||||
* immediately purge it
|
||||
*/
|
||||
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);
|
||||
|
||||
/* decrease the reference held for this vlan */
|
||||
vlan = batadv_softif_vlan_get(bat_priv, vid);
|
||||
if (!vlan)
|
||||
goto out;
|
||||
|
||||
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 */
|
||||
vlan = batadv_softif_vlan_get(bat_priv,
|
||||
tt_common_entry->vid);
|
||||
batadv_softif_vlan_free_ref(vlan);
|
||||
batadv_softif_vlan_free_ref(vlan);
|
||||
if (vlan) {
|
||||
batadv_softif_vlan_free_ref(vlan);
|
||||
batadv_softif_vlan_free_ref(vlan);
|
||||
}
|
||||
|
||||
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 */
|
||||
vlan = batadv_softif_vlan_get(bat_priv, tt_common->vid);
|
||||
batadv_softif_vlan_free_ref(vlan);
|
||||
batadv_softif_vlan_free_ref(vlan);
|
||||
if (vlan) {
|
||||
batadv_softif_vlan_free_ref(vlan);
|
||||
batadv_softif_vlan_free_ref(vlan);
|
||||
}
|
||||
|
||||
batadv_tt_local_entry_free_ref(tt_local);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user