diff options
author | David S. Miller <davem@davemloft.net> | 2015-08-07 18:51:10 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2015-08-07 18:51:10 -0400 |
commit | 95a428f3be450350773fff3a5aabfd4de1a59fc7 (patch) | |
tree | 3b5d14bf1604c052aa646489891a161cbbdcb75b | |
parent | d1163e91ce1efab514468085924de3b7afa1b0ca (diff) | |
parent | 27a4d5efd417b6ef3190e9af357715532d4617a3 (diff) |
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>
-rw-r--r-- | net/batman-adv/distributed-arp-table.c | 18 | ||||
-rw-r--r-- | net/batman-adv/gateway_client.c | 2 | ||||
-rw-r--r-- | net/batman-adv/soft-interface.c | 3 | ||||
-rw-r--r-- | net/batman-adv/translation-table.c | 29 |
4 files changed, 42 insertions, 10 deletions
diff --git a/net/batman-adv/distributed-arp-table.c b/net/batman-adv/distributed-arp-table.c index fb54e6aed096..6d0b471eede8 100644 --- a/net/batman-adv/distributed-arp-table.c +++ b/net/batman-adv/distributed-arp-table.c | |||
@@ -1138,6 +1138,9 @@ void batadv_dat_snoop_outgoing_arp_reply(struct batadv_priv *bat_priv, | |||
1138 | * @bat_priv: the bat priv with all the soft interface information | 1138 | * @bat_priv: the bat priv with all the soft interface information |
1139 | * @skb: packet to check | 1139 | * @skb: packet to check |
1140 | * @hdr_size: size of the encapsulation header | 1140 | * @hdr_size: size of the encapsulation header |
1141 | * | ||
1142 | * Returns true if the packet was snooped and consumed by DAT. False if the | ||
1143 | * packet has to be delivered to the interface | ||
1141 | */ | 1144 | */ |
1142 | bool batadv_dat_snoop_incoming_arp_reply(struct batadv_priv *bat_priv, | 1145 | bool batadv_dat_snoop_incoming_arp_reply(struct batadv_priv *bat_priv, |
1143 | struct sk_buff *skb, int hdr_size) | 1146 | struct sk_buff *skb, int hdr_size) |
@@ -1145,7 +1148,7 @@ bool batadv_dat_snoop_incoming_arp_reply(struct batadv_priv *bat_priv, | |||
1145 | uint16_t type; | 1148 | uint16_t type; |
1146 | __be32 ip_src, ip_dst; | 1149 | __be32 ip_src, ip_dst; |
1147 | uint8_t *hw_src, *hw_dst; | 1150 | uint8_t *hw_src, *hw_dst; |
1148 | bool ret = false; | 1151 | bool dropped = false; |
1149 | unsigned short vid; | 1152 | unsigned short vid; |
1150 | 1153 | ||
1151 | if (!atomic_read(&bat_priv->distributed_arp_table)) | 1154 | if (!atomic_read(&bat_priv->distributed_arp_table)) |
@@ -1174,12 +1177,17 @@ bool batadv_dat_snoop_incoming_arp_reply(struct batadv_priv *bat_priv, | |||
1174 | /* if this REPLY is directed to a client of mine, let's deliver the | 1177 | /* if this REPLY is directed to a client of mine, let's deliver the |
1175 | * packet to the interface | 1178 | * packet to the interface |
1176 | */ | 1179 | */ |
1177 | ret = !batadv_is_my_client(bat_priv, hw_dst, vid); | 1180 | dropped = !batadv_is_my_client(bat_priv, hw_dst, vid); |
1181 | |||
1182 | /* if this REPLY is sent on behalf of a client of mine, let's drop the | ||
1183 | * packet because the client will reply by itself | ||
1184 | */ | ||
1185 | dropped |= batadv_is_my_client(bat_priv, hw_src, vid); | ||
1178 | out: | 1186 | out: |
1179 | if (ret) | 1187 | if (dropped) |
1180 | kfree_skb(skb); | 1188 | kfree_skb(skb); |
1181 | /* if ret == false -> packet has to be delivered to the interface */ | 1189 | /* if dropped == false -> deliver to the interface */ |
1182 | return ret; | 1190 | return dropped; |
1183 | } | 1191 | } |
1184 | 1192 | ||
1185 | /** | 1193 | /** |
diff --git a/net/batman-adv/gateway_client.c b/net/batman-adv/gateway_client.c index bb0158620628..cffa92dd9877 100644 --- a/net/batman-adv/gateway_client.c +++ b/net/batman-adv/gateway_client.c | |||
@@ -439,6 +439,8 @@ static void batadv_gw_node_add(struct batadv_priv *bat_priv, | |||
439 | 439 | ||
440 | INIT_HLIST_NODE(&gw_node->list); | 440 | INIT_HLIST_NODE(&gw_node->list); |
441 | gw_node->orig_node = orig_node; | 441 | gw_node->orig_node = orig_node; |
442 | gw_node->bandwidth_down = ntohl(gateway->bandwidth_down); | ||
443 | gw_node->bandwidth_up = ntohl(gateway->bandwidth_up); | ||
442 | atomic_set(&gw_node->refcount, 1); | 444 | atomic_set(&gw_node->refcount, 1); |
443 | 445 | ||
444 | spin_lock_bh(&bat_priv->gw.list_lock); | 446 | spin_lock_bh(&bat_priv->gw.list_lock); |
diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c index c002961da75d..a2fc843c2243 100644 --- a/net/batman-adv/soft-interface.c +++ b/net/batman-adv/soft-interface.c | |||
@@ -479,6 +479,9 @@ out: | |||
479 | */ | 479 | */ |
480 | void batadv_softif_vlan_free_ref(struct batadv_softif_vlan *vlan) | 480 | void batadv_softif_vlan_free_ref(struct batadv_softif_vlan *vlan) |
481 | { | 481 | { |
482 | if (!vlan) | ||
483 | return; | ||
484 | |||
482 | if (atomic_dec_and_test(&vlan->refcount)) { | 485 | if (atomic_dec_and_test(&vlan->refcount)) { |
483 | spin_lock_bh(&vlan->bat_priv->softif_vlan_list_lock); | 486 | spin_lock_bh(&vlan->bat_priv->softif_vlan_list_lock); |
484 | hlist_del_rcu(&vlan->list); | 487 | hlist_del_rcu(&vlan->list); |
diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c index b4824951010b..5e953297d3b2 100644 --- a/net/batman-adv/translation-table.c +++ b/net/batman-adv/translation-table.c | |||
@@ -594,6 +594,9 @@ bool batadv_tt_local_add(struct net_device *soft_iface, const uint8_t *addr, | |||
594 | 594 | ||
595 | /* increase the refcounter of the related vlan */ | 595 | /* increase the refcounter of the related vlan */ |
596 | vlan = batadv_softif_vlan_get(bat_priv, vid); | 596 | vlan = batadv_softif_vlan_get(bat_priv, vid); |
597 | if (WARN(!vlan, "adding TT local entry %pM to non-existent VLAN %d", | ||
598 | addr, BATADV_PRINT_VID(vid))) | ||
599 | goto out; | ||
597 | 600 | ||
598 | batadv_dbg(BATADV_DBG_TT, bat_priv, | 601 | batadv_dbg(BATADV_DBG_TT, bat_priv, |
599 | "Creating new local tt entry: %pM (vid: %d, ttvn: %d)\n", | 602 | "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, | |||
1034 | struct batadv_tt_local_entry *tt_local_entry; | 1037 | struct batadv_tt_local_entry *tt_local_entry; |
1035 | uint16_t flags, curr_flags = BATADV_NO_FLAGS; | 1038 | uint16_t flags, curr_flags = BATADV_NO_FLAGS; |
1036 | struct batadv_softif_vlan *vlan; | 1039 | struct batadv_softif_vlan *vlan; |
1040 | void *tt_entry_exists; | ||
1037 | 1041 | ||
1038 | tt_local_entry = batadv_tt_local_hash_find(bat_priv, addr, vid); | 1042 | tt_local_entry = batadv_tt_local_hash_find(bat_priv, addr, vid); |
1039 | if (!tt_local_entry) | 1043 | if (!tt_local_entry) |
@@ -1061,11 +1065,22 @@ uint16_t batadv_tt_local_remove(struct batadv_priv *bat_priv, | |||
1061 | * immediately purge it | 1065 | * immediately purge it |
1062 | */ | 1066 | */ |
1063 | batadv_tt_local_event(bat_priv, tt_local_entry, BATADV_TT_CLIENT_DEL); | 1067 | batadv_tt_local_event(bat_priv, tt_local_entry, BATADV_TT_CLIENT_DEL); |
1064 | hlist_del_rcu(&tt_local_entry->common.hash_entry); | 1068 | |
1069 | tt_entry_exists = batadv_hash_remove(bat_priv->tt.local_hash, | ||
1070 | batadv_compare_tt, | ||
1071 | batadv_choose_tt, | ||
1072 | &tt_local_entry->common); | ||
1073 | if (!tt_entry_exists) | ||
1074 | goto out; | ||
1075 | |||
1076 | /* extra call to free the local tt entry */ | ||
1065 | batadv_tt_local_entry_free_ref(tt_local_entry); | 1077 | batadv_tt_local_entry_free_ref(tt_local_entry); |
1066 | 1078 | ||
1067 | /* decrease the reference held for this vlan */ | 1079 | /* decrease the reference held for this vlan */ |
1068 | vlan = batadv_softif_vlan_get(bat_priv, vid); | 1080 | vlan = batadv_softif_vlan_get(bat_priv, vid); |
1081 | if (!vlan) | ||
1082 | goto out; | ||
1083 | |||
1069 | batadv_softif_vlan_free_ref(vlan); | 1084 | batadv_softif_vlan_free_ref(vlan); |
1070 | batadv_softif_vlan_free_ref(vlan); | 1085 | batadv_softif_vlan_free_ref(vlan); |
1071 | 1086 | ||
@@ -1166,8 +1181,10 @@ static void batadv_tt_local_table_free(struct batadv_priv *bat_priv) | |||
1166 | /* decrease the reference held for this vlan */ | 1181 | /* decrease the reference held for this vlan */ |
1167 | vlan = batadv_softif_vlan_get(bat_priv, | 1182 | vlan = batadv_softif_vlan_get(bat_priv, |
1168 | tt_common_entry->vid); | 1183 | tt_common_entry->vid); |
1169 | batadv_softif_vlan_free_ref(vlan); | 1184 | if (vlan) { |
1170 | batadv_softif_vlan_free_ref(vlan); | 1185 | batadv_softif_vlan_free_ref(vlan); |
1186 | batadv_softif_vlan_free_ref(vlan); | ||
1187 | } | ||
1171 | 1188 | ||
1172 | batadv_tt_local_entry_free_ref(tt_local); | 1189 | batadv_tt_local_entry_free_ref(tt_local); |
1173 | } | 1190 | } |
@@ -3207,8 +3224,10 @@ static void batadv_tt_local_purge_pending_clients(struct batadv_priv *bat_priv) | |||
3207 | 3224 | ||
3208 | /* decrease the reference held for this vlan */ | 3225 | /* decrease the reference held for this vlan */ |
3209 | vlan = batadv_softif_vlan_get(bat_priv, tt_common->vid); | 3226 | vlan = batadv_softif_vlan_get(bat_priv, tt_common->vid); |
3210 | batadv_softif_vlan_free_ref(vlan); | 3227 | if (vlan) { |
3211 | batadv_softif_vlan_free_ref(vlan); | 3228 | batadv_softif_vlan_free_ref(vlan); |
3229 | batadv_softif_vlan_free_ref(vlan); | ||
3230 | } | ||
3212 | 3231 | ||
3213 | batadv_tt_local_entry_free_ref(tt_local); | 3232 | batadv_tt_local_entry_free_ref(tt_local); |
3214 | } | 3233 | } |