aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAllan Stephens <Allan.Stephens@windriver.com>2011-02-23 13:51:15 -0500
committerPaul Gortmaker <paul.gortmaker@windriver.com>2011-03-13 16:35:16 -0400
commit431697eb60d2d36614096aff12bd1b826a9f9bc1 (patch)
treeb9923f1d8b90438920fe16b6f3650a3ce40d6147
parenta3796f895ff2917aea331a8d40036c73452b2203 (diff)
tipc: Prevent null pointer error when removing a node subscription
Prevents a null pointer dereference from occurring if a node subscription is triggered at the same time that the subscribing port or publication is terminating the subscription. The problem arises if the triggering routine asynchronously activates and deregisters the node subscription while deregistration is already underway -- the deregistration routine may find that the pointer it has just verified to be non-NULL is now NULL. To avoid this race condition the triggering routine now simply marks the node subscription as defunct (to prevent it from re-activating) instead of deregistering it. The subscription is now both deregistered and destroyed only when the subscribing port or publication code terminates the node subscription. Signed-off-by: Allan Stephens <Allan.Stephens@windriver.com> Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
-rw-r--r--net/tipc/name_distr.c5
-rw-r--r--net/tipc/node.c13
2 files changed, 10 insertions, 8 deletions
diff --git a/net/tipc/name_distr.c b/net/tipc/name_distr.c
index 483c226c9581..1d4a18aa9ccc 100644
--- a/net/tipc/name_distr.c
+++ b/net/tipc/name_distr.c
@@ -2,7 +2,7 @@
2 * net/tipc/name_distr.c: TIPC name distribution code 2 * net/tipc/name_distr.c: TIPC name distribution code
3 * 3 *
4 * Copyright (c) 2000-2006, Ericsson AB 4 * Copyright (c) 2000-2006, Ericsson AB
5 * Copyright (c) 2005, Wind River Systems 5 * Copyright (c) 2005, 2010-2011, Wind River Systems
6 * All rights reserved. 6 * All rights reserved.
7 * 7 *
8 * Redistribution and use in source and binary forms, with or without 8 * Redistribution and use in source and binary forms, with or without
@@ -221,7 +221,6 @@ exit:
221 * In rare cases the link may have come back up again when this 221 * In rare cases the link may have come back up again when this
222 * function is called, and we have two items representing the same 222 * function is called, and we have two items representing the same
223 * publication. Nudge this item's key to distinguish it from the other. 223 * publication. Nudge this item's key to distinguish it from the other.
224 * (Note: Publication's node subscription is already unsubscribed.)
225 */ 224 */
226 225
227static void node_is_down(struct publication *publ) 226static void node_is_down(struct publication *publ)
@@ -232,6 +231,8 @@ static void node_is_down(struct publication *publ)
232 publ->key += 1222345; 231 publ->key += 1222345;
233 p = tipc_nametbl_remove_publ(publ->type, publ->lower, 232 p = tipc_nametbl_remove_publ(publ->type, publ->lower,
234 publ->node, publ->ref, publ->key); 233 publ->node, publ->ref, publ->key);
234 if (p)
235 tipc_nodesub_unsubscribe(&p->subscr);
235 write_unlock_bh(&tipc_nametbl_lock); 236 write_unlock_bh(&tipc_nametbl_lock);
236 237
237 if (p != publ) { 238 if (p != publ) {
diff --git a/net/tipc/node.c b/net/tipc/node.c
index 14f98c81d313..8926caaf1fc5 100644
--- a/net/tipc/node.c
+++ b/net/tipc/node.c
@@ -327,7 +327,7 @@ static void node_cleanup_finished(unsigned long node_addr)
327 327
328static void node_lost_contact(struct tipc_node *n_ptr) 328static void node_lost_contact(struct tipc_node *n_ptr)
329{ 329{
330 struct tipc_node_subscr *ns, *tns; 330 struct tipc_node_subscr *ns;
331 char addr_string[16]; 331 char addr_string[16];
332 u32 i; 332 u32 i;
333 333
@@ -365,11 +365,12 @@ static void node_lost_contact(struct tipc_node *n_ptr)
365 } 365 }
366 366
367 /* Notify subscribers */ 367 /* Notify subscribers */
368 list_for_each_entry_safe(ns, tns, &n_ptr->nsub, nodesub_list) { 368 list_for_each_entry(ns, &n_ptr->nsub, nodesub_list) {
369 ns->node = NULL; 369 if (ns->handle_node_down) {
370 list_del_init(&ns->nodesub_list); 370 tipc_k_signal((Handler)ns->handle_node_down,
371 tipc_k_signal((Handler)ns->handle_node_down, 371 (unsigned long)ns->usr_handle);
372 (unsigned long)ns->usr_handle); 372 ns->handle_node_down = NULL;
373 }
373 } 374 }
374 375
375 /* Prevent re-contact with node until all cleanup is done */ 376 /* Prevent re-contact with node until all cleanup is done */