diff options
author | Simon Wunderlich <simon.wunderlich@s2003.tu-chemnitz.de> | 2011-11-02 15:26:45 -0400 |
---|---|---|
committer | Sven Eckelmann <sven@narfation.org> | 2011-11-20 07:08:36 -0500 |
commit | 80b3f58cf416770ae89b30734d252d641a56d289 (patch) | |
tree | 2ec071472dd768a3e867fe12e003c7bc3026eee5 /net/batman-adv/translation-table.c | |
parent | 697f25314a923f75deef0d3b10991dd103f59d93 (diff) |
batman-adv: check return value for hash_add()
if hash_add() fails, we should remove the structure to avoid memory
leaks.
Signed-off-by: Simon Wunderlich <siwu@hrz.tu-chemnitz.de>
Acked-by: Antonio Quartulli <ordex@autistici.org>
Signed-off-by: Sven Eckelmann <sven@narfation.org>
Diffstat (limited to 'net/batman-adv/translation-table.c')
-rw-r--r-- | net/batman-adv/translation-table.c | 28 |
1 files changed, 22 insertions, 6 deletions
diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c index f6bbd6423def..cc87acf02431 100644 --- a/net/batman-adv/translation-table.c +++ b/net/batman-adv/translation-table.c | |||
@@ -190,6 +190,7 @@ void tt_local_add(struct net_device *soft_iface, const uint8_t *addr, | |||
190 | struct bat_priv *bat_priv = netdev_priv(soft_iface); | 190 | struct bat_priv *bat_priv = netdev_priv(soft_iface); |
191 | struct tt_local_entry *tt_local_entry = NULL; | 191 | struct tt_local_entry *tt_local_entry = NULL; |
192 | struct tt_global_entry *tt_global_entry = NULL; | 192 | struct tt_global_entry *tt_global_entry = NULL; |
193 | int hash_added; | ||
193 | 194 | ||
194 | tt_local_entry = tt_local_hash_find(bat_priv, addr); | 195 | tt_local_entry = tt_local_hash_find(bat_priv, addr); |
195 | 196 | ||
@@ -217,6 +218,16 @@ void tt_local_add(struct net_device *soft_iface, const uint8_t *addr, | |||
217 | if (compare_eth(addr, soft_iface->dev_addr)) | 218 | if (compare_eth(addr, soft_iface->dev_addr)) |
218 | tt_local_entry->common.flags |= TT_CLIENT_NOPURGE; | 219 | tt_local_entry->common.flags |= TT_CLIENT_NOPURGE; |
219 | 220 | ||
221 | hash_added = hash_add(bat_priv->tt_local_hash, compare_tt, choose_orig, | ||
222 | &tt_local_entry->common, | ||
223 | &tt_local_entry->common.hash_entry); | ||
224 | |||
225 | if (unlikely(hash_added != 0)) { | ||
226 | /* remove the reference for the hash */ | ||
227 | tt_local_entry_free_ref(tt_local_entry); | ||
228 | goto out; | ||
229 | } | ||
230 | |||
220 | tt_local_event(bat_priv, addr, tt_local_entry->common.flags); | 231 | tt_local_event(bat_priv, addr, tt_local_entry->common.flags); |
221 | 232 | ||
222 | /* The local entry has to be marked as NEW to avoid to send it in | 233 | /* The local entry has to be marked as NEW to avoid to send it in |
@@ -224,9 +235,6 @@ void tt_local_add(struct net_device *soft_iface, const uint8_t *addr, | |||
224 | * (consistency check) */ | 235 | * (consistency check) */ |
225 | tt_local_entry->common.flags |= TT_CLIENT_NEW; | 236 | tt_local_entry->common.flags |= TT_CLIENT_NEW; |
226 | 237 | ||
227 | hash_add(bat_priv->tt_local_hash, compare_tt, choose_orig, | ||
228 | &tt_local_entry->common, &tt_local_entry->common.hash_entry); | ||
229 | |||
230 | /* remove address from global hash if present */ | 238 | /* remove address from global hash if present */ |
231 | tt_global_entry = tt_global_hash_find(bat_priv, addr); | 239 | tt_global_entry = tt_global_hash_find(bat_priv, addr); |
232 | 240 | ||
@@ -499,6 +507,7 @@ int tt_global_add(struct bat_priv *bat_priv, struct orig_node *orig_node, | |||
499 | struct tt_global_entry *tt_global_entry; | 507 | struct tt_global_entry *tt_global_entry; |
500 | struct orig_node *orig_node_tmp; | 508 | struct orig_node *orig_node_tmp; |
501 | int ret = 0; | 509 | int ret = 0; |
510 | int hash_added; | ||
502 | 511 | ||
503 | tt_global_entry = tt_global_hash_find(bat_priv, tt_addr); | 512 | tt_global_entry = tt_global_hash_find(bat_priv, tt_addr); |
504 | 513 | ||
@@ -518,9 +527,15 @@ int tt_global_add(struct bat_priv *bat_priv, struct orig_node *orig_node, | |||
518 | tt_global_entry->ttvn = ttvn; | 527 | tt_global_entry->ttvn = ttvn; |
519 | tt_global_entry->roam_at = 0; | 528 | tt_global_entry->roam_at = 0; |
520 | 529 | ||
521 | hash_add(bat_priv->tt_global_hash, compare_tt, | 530 | hash_added = hash_add(bat_priv->tt_global_hash, compare_tt, |
522 | choose_orig, &tt_global_entry->common, | 531 | choose_orig, &tt_global_entry->common, |
523 | &tt_global_entry->common.hash_entry); | 532 | &tt_global_entry->common.hash_entry); |
533 | |||
534 | if (unlikely(hash_added != 0)) { | ||
535 | /* remove the reference for the hash */ | ||
536 | tt_global_entry_free_ref(tt_global_entry); | ||
537 | goto out_remove; | ||
538 | } | ||
524 | atomic_inc(&orig_node->tt_size); | 539 | atomic_inc(&orig_node->tt_size); |
525 | } else { | 540 | } else { |
526 | if (tt_global_entry->orig_node != orig_node) { | 541 | if (tt_global_entry->orig_node != orig_node) { |
@@ -543,6 +558,7 @@ int tt_global_add(struct bat_priv *bat_priv, struct orig_node *orig_node, | |||
543 | "Creating new global tt entry: %pM (via %pM)\n", | 558 | "Creating new global tt entry: %pM (via %pM)\n", |
544 | tt_global_entry->common.addr, orig_node->orig); | 559 | tt_global_entry->common.addr, orig_node->orig); |
545 | 560 | ||
561 | out_remove: | ||
546 | /* remove address from local hash if present */ | 562 | /* remove address from local hash if present */ |
547 | tt_local_remove(bat_priv, tt_global_entry->common.addr, | 563 | tt_local_remove(bat_priv, tt_global_entry->common.addr, |
548 | "global tt received", roaming); | 564 | "global tt received", roaming); |