Commit bab7c6c3 authored by Sven Eckelmann's avatar Sven Eckelmann Committed by Antonio Quartulli

batman-adv: Fix list removal of batadv_hardif_neigh_node

The neigh_list with batadv_hardif_neigh_node objects is accessed with only
rcu_read_lock in batadv_hardif_neigh_get and batadv_iv_neigh_print. Thus it
is not allowed to kfree the object before the rcu grace period ends (which
may still protects context accessing this object). Therefore the object has
first to be removed from the neigh_list and then it has either wait with
synchronize_rcu or call_rcu till the grace period ends before it can be
freed.

Fixes: cef63419 ("batman-adv: add list of unique single hop neighbors per hard-interface")
Signed-off-by: default avatarSven Eckelmann <sven@narfation.org>
Signed-off-by: default avatarMarek Lindner <mareklindner@neomailbox.ch>
Signed-off-by: default avatarAntonio Quartulli <a@unstable.cc>
parent af63cf51
...@@ -211,10 +211,6 @@ static void batadv_hardif_neigh_free_rcu(struct rcu_head *rcu) ...@@ -211,10 +211,6 @@ static void batadv_hardif_neigh_free_rcu(struct rcu_head *rcu)
hardif_neigh = container_of(rcu, struct batadv_hardif_neigh_node, rcu); hardif_neigh = container_of(rcu, struct batadv_hardif_neigh_node, rcu);
spin_lock_bh(&hardif_neigh->if_incoming->neigh_list_lock);
hlist_del_init_rcu(&hardif_neigh->list);
spin_unlock_bh(&hardif_neigh->if_incoming->neigh_list_lock);
batadv_hardif_free_ref_now(hardif_neigh->if_incoming); batadv_hardif_free_ref_now(hardif_neigh->if_incoming);
kfree(hardif_neigh); kfree(hardif_neigh);
} }
...@@ -227,8 +223,13 @@ static void batadv_hardif_neigh_free_rcu(struct rcu_head *rcu) ...@@ -227,8 +223,13 @@ static void batadv_hardif_neigh_free_rcu(struct rcu_head *rcu)
static void static void
batadv_hardif_neigh_free_now(struct batadv_hardif_neigh_node *hardif_neigh) batadv_hardif_neigh_free_now(struct batadv_hardif_neigh_node *hardif_neigh)
{ {
if (atomic_dec_and_test(&hardif_neigh->refcount)) if (atomic_dec_and_test(&hardif_neigh->refcount)) {
spin_lock_bh(&hardif_neigh->if_incoming->neigh_list_lock);
hlist_del_init_rcu(&hardif_neigh->list);
spin_unlock_bh(&hardif_neigh->if_incoming->neigh_list_lock);
batadv_hardif_neigh_free_rcu(&hardif_neigh->rcu); batadv_hardif_neigh_free_rcu(&hardif_neigh->rcu);
}
} }
/** /**
...@@ -238,8 +239,13 @@ batadv_hardif_neigh_free_now(struct batadv_hardif_neigh_node *hardif_neigh) ...@@ -238,8 +239,13 @@ batadv_hardif_neigh_free_now(struct batadv_hardif_neigh_node *hardif_neigh)
*/ */
void batadv_hardif_neigh_free_ref(struct batadv_hardif_neigh_node *hardif_neigh) void batadv_hardif_neigh_free_ref(struct batadv_hardif_neigh_node *hardif_neigh)
{ {
if (atomic_dec_and_test(&hardif_neigh->refcount)) if (atomic_dec_and_test(&hardif_neigh->refcount)) {
spin_lock_bh(&hardif_neigh->if_incoming->neigh_list_lock);
hlist_del_init_rcu(&hardif_neigh->list);
spin_unlock_bh(&hardif_neigh->if_incoming->neigh_list_lock);
call_rcu(&hardif_neigh->rcu, batadv_hardif_neigh_free_rcu); call_rcu(&hardif_neigh->rcu, batadv_hardif_neigh_free_rcu);
}
} }
/** /**
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment