aboutsummaryrefslogtreecommitdiffstats
path: root/net/batman-adv/routing.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/routing.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/routing.c')
-rw-r--r--net/batman-adv/routing.c24
1 files changed, 12 insertions, 12 deletions
diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c
index fc4c12a049da..9863c03a2137 100644
--- a/net/batman-adv/routing.c
+++ b/net/batman-adv/routing.c
@@ -420,7 +420,7 @@ static void update_orig(struct bat_priv *bat_priv,
420 neigh_node = create_neighbor(orig_node, orig_tmp, 420 neigh_node = create_neighbor(orig_node, orig_tmp,
421 ethhdr->h_source, if_incoming); 421 ethhdr->h_source, if_incoming);
422 422
423 kref_put(&orig_tmp->refcount, orig_node_free_ref); 423 orig_node_free_ref(orig_tmp);
424 if (!neigh_node) 424 if (!neigh_node)
425 goto unlock; 425 goto unlock;
426 426
@@ -604,7 +604,7 @@ static char count_real_packets(struct ethhdr *ethhdr,
604 604
605out: 605out:
606 spin_unlock_bh(&orig_node->ogm_cnt_lock); 606 spin_unlock_bh(&orig_node->ogm_cnt_lock);
607 kref_put(&orig_node->refcount, orig_node_free_ref); 607 orig_node_free_ref(orig_node);
608 return ret; 608 return ret;
609} 609}
610 610
@@ -730,7 +730,7 @@ void receive_bat_packet(struct ethhdr *ethhdr,
730 730
731 bat_dbg(DBG_BATMAN, bat_priv, "Drop packet: " 731 bat_dbg(DBG_BATMAN, bat_priv, "Drop packet: "
732 "originator packet from myself (via neighbor)\n"); 732 "originator packet from myself (via neighbor)\n");
733 kref_put(&orig_neigh_node->refcount, orig_node_free_ref); 733 orig_node_free_ref(orig_neigh_node);
734 return; 734 return;
735 } 735 }
736 736
@@ -835,10 +835,10 @@ void receive_bat_packet(struct ethhdr *ethhdr,
835 0, hna_buff_len, if_incoming); 835 0, hna_buff_len, if_incoming);
836 836
837out_neigh: 837out_neigh:
838 if (!is_single_hop_neigh) 838 if ((orig_neigh_node) && (!is_single_hop_neigh))
839 kref_put(&orig_neigh_node->refcount, orig_node_free_ref); 839 orig_node_free_ref(orig_neigh_node);
840out: 840out:
841 kref_put(&orig_node->refcount, orig_node_free_ref); 841 orig_node_free_ref(orig_node);
842} 842}
843 843
844int recv_bat_packet(struct sk_buff *skb, struct batman_if *batman_if) 844int recv_bat_packet(struct sk_buff *skb, struct batman_if *batman_if)
@@ -952,7 +952,7 @@ out:
952 if (neigh_node) 952 if (neigh_node)
953 neigh_node_free_ref(neigh_node); 953 neigh_node_free_ref(neigh_node);
954 if (orig_node) 954 if (orig_node)
955 kref_put(&orig_node->refcount, orig_node_free_ref); 955 orig_node_free_ref(orig_node);
956 return ret; 956 return ret;
957} 957}
958 958
@@ -1028,7 +1028,7 @@ out:
1028 if (neigh_node) 1028 if (neigh_node)
1029 neigh_node_free_ref(neigh_node); 1029 neigh_node_free_ref(neigh_node);
1030 if (orig_node) 1030 if (orig_node)
1031 kref_put(&orig_node->refcount, orig_node_free_ref); 1031 orig_node_free_ref(orig_node);
1032 return ret; 1032 return ret;
1033} 1033}
1034 1034
@@ -1134,7 +1134,7 @@ out:
1134 if (neigh_node) 1134 if (neigh_node)
1135 neigh_node_free_ref(neigh_node); 1135 neigh_node_free_ref(neigh_node);
1136 if (orig_node) 1136 if (orig_node)
1137 kref_put(&orig_node->refcount, orig_node_free_ref); 1137 orig_node_free_ref(orig_node);
1138 return ret; 1138 return ret;
1139} 1139}
1140 1140
@@ -1189,7 +1189,7 @@ struct neigh_node *find_router(struct bat_priv *bat_priv,
1189 if (!primary_orig_node) 1189 if (!primary_orig_node)
1190 goto return_router; 1190 goto return_router;
1191 1191
1192 kref_put(&primary_orig_node->refcount, orig_node_free_ref); 1192 orig_node_free_ref(primary_orig_node);
1193 } 1193 }
1194 1194
1195 /* with less than 2 candidates, we can't do any 1195 /* with less than 2 candidates, we can't do any
@@ -1401,7 +1401,7 @@ out:
1401 if (neigh_node) 1401 if (neigh_node)
1402 neigh_node_free_ref(neigh_node); 1402 neigh_node_free_ref(neigh_node);
1403 if (orig_node) 1403 if (orig_node)
1404 kref_put(&orig_node->refcount, orig_node_free_ref); 1404 orig_node_free_ref(orig_node);
1405 return ret; 1405 return ret;
1406} 1406}
1407 1407
@@ -1543,7 +1543,7 @@ spin_unlock:
1543 spin_unlock_bh(&bat_priv->orig_hash_lock); 1543 spin_unlock_bh(&bat_priv->orig_hash_lock);
1544out: 1544out:
1545 if (orig_node) 1545 if (orig_node)
1546 kref_put(&orig_node->refcount, orig_node_free_ref); 1546 orig_node_free_ref(orig_node);
1547 return ret; 1547 return ret;
1548} 1548}
1549 1549