aboutsummaryrefslogtreecommitdiffstats
path: root/net/tipc
diff options
context:
space:
mode:
authorRichard Alpe <richard.alpe@ericsson.com>2014-12-10 03:46:54 -0500
committerDavid S. Miller <davem@davemloft.net>2014-12-10 14:45:33 -0500
commit340b6e59fbc6ac97469253315c96e952908c9c0d (patch)
treed88c379f281f793b0b4f333a8fde018466bc1a6a /net/tipc
parent4f675eb2a736dfb65d68a00ff38e9342252eeabc (diff)
tipc: fix broadcast wakeup contention after congestion
commit 908344cdda80 ("tipc: fix bug in multicast congestion handling") introduced a race in the broadcast link wakeup functionality. This patch eliminates this broadcast link wakeup race caused by operation on the wakeup list without proper locking. If this race hit and corrupted the list all subsequent wakeup messages would be lost, resulting in a considerable memory leak. Signed-off-by: Richard Alpe <richard.alpe@ericsson.com> Signed-off-by: Erik Hugne <erik.hugne@ericsson.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/tipc')
-rw-r--r--net/tipc/link.c8
-rw-r--r--net/tipc/node.c2
2 files changed, 5 insertions, 5 deletions
diff --git a/net/tipc/link.c b/net/tipc/link.c
index 34bf15c90c78..23bcc1132365 100644
--- a/net/tipc/link.c
+++ b/net/tipc/link.c
@@ -293,7 +293,7 @@ struct tipc_link *tipc_link_create(struct tipc_node *n_ptr,
293 l_ptr->next_out_no = 1; 293 l_ptr->next_out_no = 1;
294 __skb_queue_head_init(&l_ptr->outqueue); 294 __skb_queue_head_init(&l_ptr->outqueue);
295 __skb_queue_head_init(&l_ptr->deferred_queue); 295 __skb_queue_head_init(&l_ptr->deferred_queue);
296 __skb_queue_head_init(&l_ptr->waiting_sks); 296 skb_queue_head_init(&l_ptr->waiting_sks);
297 297
298 link_reset_statistics(l_ptr); 298 link_reset_statistics(l_ptr);
299 299
@@ -358,7 +358,7 @@ static bool link_schedule_user(struct tipc_link *link, u32 oport,
358 return false; 358 return false;
359 TIPC_SKB_CB(buf)->chain_sz = chain_sz; 359 TIPC_SKB_CB(buf)->chain_sz = chain_sz;
360 TIPC_SKB_CB(buf)->chain_imp = imp; 360 TIPC_SKB_CB(buf)->chain_imp = imp;
361 __skb_queue_tail(&link->waiting_sks, buf); 361 skb_queue_tail(&link->waiting_sks, buf);
362 link->stats.link_congs++; 362 link->stats.link_congs++;
363 return true; 363 return true;
364} 364}
@@ -378,8 +378,8 @@ static void link_prepare_wakeup(struct tipc_link *link)
378 if (pend_qsz >= link->queue_limit[TIPC_SKB_CB(skb)->chain_imp]) 378 if (pend_qsz >= link->queue_limit[TIPC_SKB_CB(skb)->chain_imp])
379 break; 379 break;
380 pend_qsz += TIPC_SKB_CB(skb)->chain_sz; 380 pend_qsz += TIPC_SKB_CB(skb)->chain_sz;
381 __skb_unlink(skb, &link->waiting_sks); 381 skb_unlink(skb, &link->waiting_sks);
382 __skb_queue_tail(&link->owner->waiting_sks, skb); 382 skb_queue_tail(&link->owner->waiting_sks, skb);
383 } 383 }
384} 384}
385 385
diff --git a/net/tipc/node.c b/net/tipc/node.c
index 69b96be09a86..8d353ec77a66 100644
--- a/net/tipc/node.c
+++ b/net/tipc/node.c
@@ -115,7 +115,7 @@ struct tipc_node *tipc_node_create(u32 addr)
115 INIT_LIST_HEAD(&n_ptr->list); 115 INIT_LIST_HEAD(&n_ptr->list);
116 INIT_LIST_HEAD(&n_ptr->publ_list); 116 INIT_LIST_HEAD(&n_ptr->publ_list);
117 INIT_LIST_HEAD(&n_ptr->conn_sks); 117 INIT_LIST_HEAD(&n_ptr->conn_sks);
118 __skb_queue_head_init(&n_ptr->waiting_sks); 118 skb_queue_head_init(&n_ptr->waiting_sks);
119 __skb_queue_head_init(&n_ptr->bclink.deferred_queue); 119 __skb_queue_head_init(&n_ptr->bclink.deferred_queue);
120 120
121 hlist_add_head_rcu(&n_ptr->hash, &node_htable[tipc_hashfn(addr)]); 121 hlist_add_head_rcu(&n_ptr->hash, &node_htable[tipc_hashfn(addr)]);