batman-adv: fix potential orig_node reference leak
Commit Message
Since batadv_orig_node_new() does not add the originator into the orig
hash, it should only return the created orig_node object with a refcount
of one (for the object return). Otherwise batadv_iv_ogm_orig_get() will
not free the orig_node correctly when allocating its private structures
or adding to the hash fails (refcount will just be decreased to one) and
eventually leak it.
Reported-by: Antonio Quartulli <antonio@meshcoding.com>
Signed-off-by: Simon Wunderlich <sw@simonwunderlich.de>
---
bat_iv_ogm.c | 8 +++++++-
originator.c | 3 +--
2 files changed, 8 insertions(+), 3 deletions(-)
@@ -243,11 +243,17 @@ batadv_iv_ogm_orig_get(struct batadv_priv *bat_priv, const uint8_t *addr)
if (!orig_node->bat_iv.bcast_own_sum)
goto free_bcast_own;
+ /* increase refcount for the hash reference */
+ if (atomic_inc_not_zero(&orig_node->refcount))
+ goto free_bcast_own;
+
hash_added = batadv_hash_add(bat_priv->orig_hash, batadv_compare_orig,
batadv_choose_orig, orig_node,
&orig_node->hash_entry);
- if (hash_added != 0)
+ if (hash_added != 0) {
+ batadv_orig_node_free_ref(orig_node);
goto free_bcast_own;
+ }
return orig_node;
@@ -625,8 +625,7 @@ struct batadv_orig_node *batadv_orig_node_new(struct batadv_priv *bat_priv,
batadv_nc_init_orig(orig_node);
- /* extra reference for return */
- atomic_set(&orig_node->refcount, 2);
+ atomic_set(&orig_node->refcount, 1);
orig_node->tt_initialised = false;
orig_node->bat_priv = bat_priv;