aboutsummaryrefslogtreecommitdiffstats
path: root/net/tipc/link.c
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/link.c
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/link.c')
-rw-r--r--net/tipc/link.c8
1 files changed, 4 insertions, 4 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