Skip to content

Commit abe59c6

Browse files
ecsvordex
authored andcommitted
batman-adv: Fix reference counting of hardif_neigh_node object for neigh_node
The batadv_neigh_node was specific to a batadv_hardif_neigh_node and held an implicit reference to it. But this reference was never stored in form of a pointer in the batadv_neigh_node itself. Instead batadv_neigh_node_release depends on a consistent state of hard_iface->neigh_list and that batadv_hardif_neigh_get always returns the batadv_hardif_neigh_node object which it has a reference for. But batadv_hardif_neigh_get cannot guarantee that because it is working only with rcu_read_lock on this list. It can therefore happen that a neigh_addr is in this list twice or that batadv_hardif_neigh_get cannot find the batadv_hardif_neigh_node for an neigh_addr due to some other list operations taking place at the same time. Instead add a batadv_hardif_neigh_node pointer directly in batadv_neigh_node which will be used for the reference counter decremented on release of batadv_neigh_node. Fixes: cef6341 ("batman-adv: add list of unique single hop neighbors per hard-interface") Signed-off-by: Sven Eckelmann <sven@narfation.org> Signed-off-by: Marek Lindner <mareklindner@neomailbox.ch> Signed-off-by: Antonio Quartulli <a@unstable.cc>
1 parent a33d970 commit abe59c6

File tree

2 files changed

+7
-11
lines changed

2 files changed

+7
-11
lines changed

net/batman-adv/originator.c

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,6 @@ static void batadv_neigh_node_release(struct kref *ref)
250250
{
251251
struct hlist_node *node_tmp;
252252
struct batadv_neigh_node *neigh_node;
253-
struct batadv_hardif_neigh_node *hardif_neigh;
254253
struct batadv_neigh_ifinfo *neigh_ifinfo;
255254
struct batadv_algo_ops *bao;
256255

@@ -262,13 +261,7 @@ static void batadv_neigh_node_release(struct kref *ref)
262261
batadv_neigh_ifinfo_put(neigh_ifinfo);
263262
}
264263

265-
hardif_neigh = batadv_hardif_neigh_get(neigh_node->if_incoming,
266-
neigh_node->addr);
267-
if (hardif_neigh) {
268-
/* batadv_hardif_neigh_get() increases refcount too */
269-
batadv_hardif_neigh_put(hardif_neigh);
270-
batadv_hardif_neigh_put(hardif_neigh);
271-
}
264+
batadv_hardif_neigh_put(neigh_node->hardif_neigh);
272265

273266
if (bao->bat_neigh_free)
274267
bao->bat_neigh_free(neigh_node);
@@ -665,6 +658,10 @@ batadv_neigh_node_new(struct batadv_orig_node *orig_node,
665658
neigh_node->orig_node = orig_node;
666659
neigh_node->last_seen = jiffies;
667660

661+
/* increment unique neighbor refcount */
662+
kref_get(&hardif_neigh->refcount);
663+
neigh_node->hardif_neigh = hardif_neigh;
664+
668665
/* extra reference for return */
669666
kref_init(&neigh_node->refcount);
670667
kref_get(&neigh_node->refcount);
@@ -673,9 +670,6 @@ batadv_neigh_node_new(struct batadv_orig_node *orig_node,
673670
hlist_add_head_rcu(&neigh_node->list, &orig_node->neigh_list);
674671
spin_unlock_bh(&orig_node->neigh_list_lock);
675672

676-
/* increment unique neighbor refcount */
677-
kref_get(&hardif_neigh->refcount);
678-
679673
batadv_dbg(BATADV_DBG_BATMAN, orig_node->bat_priv,
680674
"Creating new neighbor %pM for orig_node %pM on interface %s\n",
681675
neigh_addr, orig_node->orig, hard_iface->net_dev->name);

net/batman-adv/types.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -433,6 +433,7 @@ struct batadv_hardif_neigh_node {
433433
* @ifinfo_lock: lock protecting private ifinfo members and list
434434
* @if_incoming: pointer to incoming hard-interface
435435
* @last_seen: when last packet via this neighbor was received
436+
* @hardif_neigh: hardif_neigh of this neighbor
436437
* @refcount: number of contexts the object is used
437438
* @rcu: struct used for freeing in an RCU-safe manner
438439
*/
@@ -444,6 +445,7 @@ struct batadv_neigh_node {
444445
spinlock_t ifinfo_lock; /* protects ifinfo_list and its members */
445446
struct batadv_hard_iface *if_incoming;
446447
unsigned long last_seen;
448+
struct batadv_hardif_neigh_node *hardif_neigh;
447449
struct kref refcount;
448450
struct rcu_head rcu;
449451
};

0 commit comments

Comments
 (0)