aboutsummaryrefslogtreecommitdiffstats
path: root/net/batman-adv/originator.c
diff options
context:
space:
mode:
authorLinus Lüssing <linus.luessing@web.de>2011-03-14 18:43:37 -0400
committerSven Eckelmann <sven@narfation.org>2011-04-17 15:11:01 -0400
commite1a5382f978b67b5cc36eec65e6046730ce07714 (patch)
treef7ca07cde3a49858d0cfa33e0189a659a1fcc95d /net/batman-adv/originator.c
parent57f0c07c4d0da8bcc23e21c330fe9c7c5cf776b5 (diff)
batman-adv: Make orig_node->router an rcu protected pointer
The rcu protected macros rcu_dereference() and rcu_assign_pointer() for the orig_node->router need to be used, as well as spin/rcu locking. Otherwise we might end up using a router pointer pointing to already freed memory. Therefore this commit introduces the safe getter method orig_node_get_router(). Signed-off-by: Linus Lüssing <linus.luessing@web.de> Signed-off-by: Marek Lindner <lindner_marek@yahoo.de> Signed-off-by: Sven Eckelmann <sven@narfation.org>
Diffstat (limited to 'net/batman-adv/originator.c')
-rw-r--r--net/batman-adv/originator.c37
1 files changed, 28 insertions, 9 deletions
diff --git a/net/batman-adv/originator.c b/net/batman-adv/originator.c
index 0b9133022d2d..b4cfe3686155 100644
--- a/net/batman-adv/originator.c
+++ b/net/batman-adv/originator.c
@@ -70,6 +70,21 @@ void neigh_node_free_ref(struct neigh_node *neigh_node)
70 call_rcu(&neigh_node->rcu, neigh_node_free_rcu); 70 call_rcu(&neigh_node->rcu, neigh_node_free_rcu);
71} 71}
72 72
73/* increases the refcounter of a found router */
74struct neigh_node *orig_node_get_router(struct orig_node *orig_node)
75{
76 struct neigh_node *router;
77
78 rcu_read_lock();
79 router = rcu_dereference(orig_node->router);
80
81 if (router && !atomic_inc_not_zero(&router->refcount))
82 router = NULL;
83
84 rcu_read_unlock();
85 return router;
86}
87
73struct neigh_node *create_neighbor(struct orig_node *orig_node, 88struct neigh_node *create_neighbor(struct orig_node *orig_node,
74 struct orig_node *orig_neigh_node, 89 struct orig_node *orig_neigh_node,
75 uint8_t *neigh, 90 uint8_t *neigh,
@@ -390,7 +405,7 @@ int orig_seq_print_text(struct seq_file *seq, void *offset)
390 struct hlist_node *node, *node_tmp; 405 struct hlist_node *node, *node_tmp;
391 struct hlist_head *head; 406 struct hlist_head *head;
392 struct orig_node *orig_node; 407 struct orig_node *orig_node;
393 struct neigh_node *neigh_node; 408 struct neigh_node *neigh_node, *neigh_node_tmp;
394 int batman_count = 0; 409 int batman_count = 0;
395 int last_seen_secs; 410 int last_seen_secs;
396 int last_seen_msecs; 411 int last_seen_msecs;
@@ -421,37 +436,41 @@ int orig_seq_print_text(struct seq_file *seq, void *offset)
421 436
422 rcu_read_lock(); 437 rcu_read_lock();
423 hlist_for_each_entry_rcu(orig_node, node, head, hash_entry) { 438 hlist_for_each_entry_rcu(orig_node, node, head, hash_entry) {
424 if (!orig_node->router) 439 neigh_node = orig_node_get_router(orig_node);
440 if (!neigh_node)
425 continue; 441 continue;
426 442
427 if (orig_node->router->tq_avg == 0) 443 if (neigh_node->tq_avg == 0)
428 continue; 444 goto next;
429 445
430 last_seen_secs = jiffies_to_msecs(jiffies - 446 last_seen_secs = jiffies_to_msecs(jiffies -
431 orig_node->last_valid) / 1000; 447 orig_node->last_valid) / 1000;
432 last_seen_msecs = jiffies_to_msecs(jiffies - 448 last_seen_msecs = jiffies_to_msecs(jiffies -
433 orig_node->last_valid) % 1000; 449 orig_node->last_valid) % 1000;
434 450
435 neigh_node = orig_node->router;
436 seq_printf(seq, "%pM %4i.%03is (%3i) %pM [%10s]:", 451 seq_printf(seq, "%pM %4i.%03is (%3i) %pM [%10s]:",
437 orig_node->orig, last_seen_secs, 452 orig_node->orig, last_seen_secs,
438 last_seen_msecs, neigh_node->tq_avg, 453 last_seen_msecs, neigh_node->tq_avg,
439 neigh_node->addr, 454 neigh_node->addr,
440 neigh_node->if_incoming->net_dev->name); 455 neigh_node->if_incoming->net_dev->name);
441 456
442 hlist_for_each_entry_rcu(neigh_node, node_tmp, 457 hlist_for_each_entry_rcu(neigh_node_tmp, node_tmp,
443 &orig_node->neigh_list, list) { 458 &orig_node->neigh_list, list) {
444 seq_printf(seq, " %pM (%3i)", neigh_node->addr, 459 seq_printf(seq, " %pM (%3i)",
445 neigh_node->tq_avg); 460 neigh_node_tmp->addr,
461 neigh_node_tmp->tq_avg);
446 } 462 }
447 463
448 seq_printf(seq, "\n"); 464 seq_printf(seq, "\n");
449 batman_count++; 465 batman_count++;
466
467next:
468 neigh_node_free_ref(neigh_node);
450 } 469 }
451 rcu_read_unlock(); 470 rcu_read_unlock();
452 } 471 }
453 472
454 if ((batman_count == 0)) 473 if (batman_count == 0)
455 seq_printf(seq, "No batman nodes in range ...\n"); 474 seq_printf(seq, "No batman nodes in range ...\n");
456 475
457 return 0; 476 return 0;