aboutsummaryrefslogtreecommitdiffstats
path: root/net/batman-adv/unicast.c
diff options
context:
space:
mode:
authorMarek Lindner <lindner_marek@yahoo.de>2011-02-18 07:28:10 -0500
committerMarek Lindner <lindner_marek@yahoo.de>2011-03-05 06:52:01 -0500
commit7b36e8eef989fc59535b4f1d3fc0f83afaf419d4 (patch)
treef0900101542966e0655ca5f115b5b0bc409b1e74 /net/batman-adv/unicast.c
parent7aadf889e897155c45cda230d2a6701ad1fbff61 (diff)
batman-adv: Correct rcu refcounting for orig_node
It might be possible that 2 threads access the same data in the same rcu grace period. The first thread calls call_rcu() to decrement the refcount and free the data while the second thread increases the refcount to use the data. To avoid this race condition all refcount operations have to be atomic. Reported-by: Sven Eckelmann <sven@narfation.org> Signed-off-by: Marek Lindner <lindner_marek@yahoo.de>
Diffstat (limited to 'net/batman-adv/unicast.c')
-rw-r--r--net/batman-adv/unicast.c6
1 files changed, 3 insertions, 3 deletions
diff --git a/net/batman-adv/unicast.c b/net/batman-adv/unicast.c
index 2d5daac52034..2ab819841231 100644
--- a/net/batman-adv/unicast.c
+++ b/net/batman-adv/unicast.c
@@ -211,7 +211,7 @@ unlock:
211 spin_unlock_bh(&bat_priv->orig_hash_lock); 211 spin_unlock_bh(&bat_priv->orig_hash_lock);
212out: 212out:
213 if (orig_node) 213 if (orig_node)
214 kref_put(&orig_node->refcount, orig_node_free_ref); 214 orig_node_free_ref(orig_node);
215 return ret; 215 return ret;
216} 216}
217 217
@@ -280,7 +280,7 @@ int unicast_send_skb(struct sk_buff *skb, struct bat_priv *bat_priv)
280{ 280{
281 struct ethhdr *ethhdr = (struct ethhdr *)skb->data; 281 struct ethhdr *ethhdr = (struct ethhdr *)skb->data;
282 struct unicast_packet *unicast_packet; 282 struct unicast_packet *unicast_packet;
283 struct orig_node *orig_node = NULL; 283 struct orig_node *orig_node;
284 struct batman_if *batman_if; 284 struct batman_if *batman_if;
285 struct neigh_node *neigh_node; 285 struct neigh_node *neigh_node;
286 int data_len = skb->len; 286 int data_len = skb->len;
@@ -347,7 +347,7 @@ out:
347 if (neigh_node) 347 if (neigh_node)
348 neigh_node_free_ref(neigh_node); 348 neigh_node_free_ref(neigh_node);
349 if (orig_node) 349 if (orig_node)
350 kref_put(&orig_node->refcount, orig_node_free_ref); 350 orig_node_free_ref(orig_node);
351 if (ret == 1) 351 if (ret == 1)
352 kfree_skb(skb); 352 kfree_skb(skb);
353 return ret; 353 return ret;