aboutsummaryrefslogtreecommitdiffstats
path: root/net/batman-adv/translation-table.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/translation-table.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/translation-table.c')
-rw-r--r--net/batman-adv/translation-table.c15
1 files changed, 9 insertions, 6 deletions
diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c
index cd8a58396d26..8d15b48d1692 100644
--- a/net/batman-adv/translation-table.c
+++ b/net/batman-adv/translation-table.c
@@ -589,17 +589,20 @@ void hna_global_free(struct bat_priv *bat_priv)
589struct orig_node *transtable_search(struct bat_priv *bat_priv, uint8_t *addr) 589struct orig_node *transtable_search(struct bat_priv *bat_priv, uint8_t *addr)
590{ 590{
591 struct hna_global_entry *hna_global_entry; 591 struct hna_global_entry *hna_global_entry;
592 struct orig_node *orig_node = NULL;
592 593
593 spin_lock_bh(&bat_priv->hna_ghash_lock); 594 spin_lock_bh(&bat_priv->hna_ghash_lock);
594 hna_global_entry = hna_global_hash_find(bat_priv, addr); 595 hna_global_entry = hna_global_hash_find(bat_priv, addr);
595 596
596 if (hna_global_entry) 597 if (!hna_global_entry)
597 kref_get(&hna_global_entry->orig_node->refcount); 598 goto out;
598 599
599 spin_unlock_bh(&bat_priv->hna_ghash_lock); 600 if (!atomic_inc_not_zero(&hna_global_entry->orig_node->refcount))
601 goto out;
600 602
601 if (!hna_global_entry) 603 orig_node = hna_global_entry->orig_node;
602 return NULL;
603 604
604 return hna_global_entry->orig_node; 605out:
606 spin_unlock_bh(&bat_priv->hna_ghash_lock);
607 return orig_node;
605} 608}