Commit 9d31b3ce81683ce3c9fd10afa70892e373b21067

Authored by Linus Lüssing
Committed by Antonio Quartulli
1 parent a5164886b0

batman-adv: fix potential TT client + orig-node memory leak

This patch fixes a potential memory leak which can occur once an
originator times out. On timeout the according global translation table
entry might not get purged correctly. Furthermore, the non purged TT
entry will cause its orig-node to leak, too. Which additionally can lead
to the new multicast optimization feature not kicking in because of a
therefore bogus counter.

In detail: The batadv_tt_global_entry->orig_list holds the reference to
the orig-node. Usually this reference is released after
BATADV_PURGE_TIMEOUT through: _batadv_purge_orig()->
batadv_purge_orig_node()->batadv_update_route()->_batadv_update_route()->
batadv_tt_global_del_orig() which purges this global tt entry and
releases the reference to the orig-node.

However, if between two batadv_purge_orig_node() calls the orig-node
timeout grew to 2*BATADV_PURGE_TIMEOUT then this call path isn't
reached. Instead the according orig-node is removed from the
originator hash in _batadv_purge_orig(), the batadv_update_route()
part is skipped and won't be reached anymore.

Fixing the issue by moving batadv_tt_global_del_orig() out of the rcu
callback.

Signed-off-by: Linus Lüssing <linus.luessing@c0d3.blue>
Acked-by: Antonio Quartulli <antonio@meshcoding.com>
Signed-off-by: Marek Lindner <mareklindner@neomailbox.ch>
Signed-off-by: Antonio Quartulli <antonio@meshcoding.com>

Showing 1 changed file with 3 additions and 3 deletions Side-by-side Diff

net/batman-adv/originator.c
... ... @@ -570,9 +570,6 @@
570 570  
571 571 batadv_frag_purge_orig(orig_node, NULL);
572 572  
573   - batadv_tt_global_del_orig(orig_node->bat_priv, orig_node, -1,
574   - "originator timed out");
575   -
576 573 if (orig_node->bat_priv->bat_algo_ops->bat_orig_free)
577 574 orig_node->bat_priv->bat_algo_ops->bat_orig_free(orig_node);
578 575  
... ... @@ -978,6 +975,9 @@
978 975 if (batadv_purge_orig_node(bat_priv, orig_node)) {
979 976 batadv_gw_node_delete(bat_priv, orig_node);
980 977 hlist_del_rcu(&orig_node->hash_entry);
  978 + batadv_tt_global_del_orig(orig_node->bat_priv,
  979 + orig_node, -1,
  980 + "originator timed out");
981 981 batadv_orig_node_free_ref(orig_node);
982 982 continue;
983 983 }