aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorSven Eckelmann <sven@narfation.org>2016-01-05 06:06:17 -0500
committerAntonio Quartulli <a@unstable.cc>2016-01-13 06:28:27 -0500
commitbab7c6c3deac70966a3000402c0ea6d0c20edd15 (patch)
treed6d644c3db05abb5451cd6811f53acd594e9c6be /net
parentaf63cf51b7f960aa73b32bac683cd4078f08fa0e (diff)
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: cef63419f7db ("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>
Diffstat (limited to 'net')
-rw-r--r--net/batman-adv/originator.c18
1 files changed, 12 insertions, 6 deletions
diff --git a/net/batman-adv/originator.c b/net/batman-adv/originator.c
index 3c782a33bdac..ae6d18cafc5a 100644
--- a/net/batman-adv/originator.c
+++ b/net/batman-adv/originator.c
@@ -211,10 +211,6 @@ static void batadv_hardif_neigh_free_rcu(struct rcu_head *rcu)
211 211
212 hardif_neigh = container_of(rcu, struct batadv_hardif_neigh_node, rcu); 212 hardif_neigh = container_of(rcu, struct batadv_hardif_neigh_node, rcu);
213 213
214 spin_lock_bh(&hardif_neigh->if_incoming->neigh_list_lock);
215 hlist_del_init_rcu(&hardif_neigh->list);
216 spin_unlock_bh(&hardif_neigh->if_incoming->neigh_list_lock);
217
218 batadv_hardif_free_ref_now(hardif_neigh->if_incoming); 214 batadv_hardif_free_ref_now(hardif_neigh->if_incoming);
219 kfree(hardif_neigh); 215 kfree(hardif_neigh);
220} 216}
@@ -227,8 +223,13 @@ static void batadv_hardif_neigh_free_rcu(struct rcu_head *rcu)
227static void 223static void
228batadv_hardif_neigh_free_now(struct batadv_hardif_neigh_node *hardif_neigh) 224batadv_hardif_neigh_free_now(struct batadv_hardif_neigh_node *hardif_neigh)
229{ 225{
230 if (atomic_dec_and_test(&hardif_neigh->refcount)) 226 if (atomic_dec_and_test(&hardif_neigh->refcount)) {
227 spin_lock_bh(&hardif_neigh->if_incoming->neigh_list_lock);
228 hlist_del_init_rcu(&hardif_neigh->list);
229 spin_unlock_bh(&hardif_neigh->if_incoming->neigh_list_lock);
230
231 batadv_hardif_neigh_free_rcu(&hardif_neigh->rcu); 231 batadv_hardif_neigh_free_rcu(&hardif_neigh->rcu);
232 }
232} 233}
233 234
234/** 235/**
@@ -238,8 +239,13 @@ batadv_hardif_neigh_free_now(struct batadv_hardif_neigh_node *hardif_neigh)
238 */ 239 */
239void batadv_hardif_neigh_free_ref(struct batadv_hardif_neigh_node *hardif_neigh) 240void batadv_hardif_neigh_free_ref(struct batadv_hardif_neigh_node *hardif_neigh)
240{ 241{
241 if (atomic_dec_and_test(&hardif_neigh->refcount)) 242 if (atomic_dec_and_test(&hardif_neigh->refcount)) {
243 spin_lock_bh(&hardif_neigh->if_incoming->neigh_list_lock);
244 hlist_del_init_rcu(&hardif_neigh->list);
245 spin_unlock_bh(&hardif_neigh->if_incoming->neigh_list_lock);
246
242 call_rcu(&hardif_neigh->rcu, batadv_hardif_neigh_free_rcu); 247 call_rcu(&hardif_neigh->rcu, batadv_hardif_neigh_free_rcu);
248 }
243} 249}
244 250
245/** 251/**