aboutsummaryrefslogtreecommitdiffstats
path: root/net/tipc
diff options
context:
space:
mode:
authorYing Xue <ying.xue@windriver.com>2014-12-02 02:00:26 -0500
committerDavid S. Miller <davem@davemloft.net>2014-12-08 20:39:56 -0500
commitfb9962f3cefeba8c5addc96dceb8bc360062ab50 (patch)
tree9a42f3c86666854a6b1221b89d4971dc9584055a /net/tipc
parent38622f41956f92a06f5b5e42e50746851110d970 (diff)
tipc: ensure all name sequences are properly protected with its lock
TIPC internally created a name table which is used to store name sequences. Now there is a read-write lock - tipc_nametbl_lock to protect the table, and each name sequence saved in the table is protected with its private lock. When a name sequence is inserted or removed to or from the table, its members might need to change. Therefore, in normal case, the two locks must be held while TIPC operates the table. However, there are still several places where we only hold tipc_nametbl_lock without proprerly obtaining name sequence lock, which might cause the corruption of name sequence. Signed-off-by: Ying Xue <ying.xue@windriver.com> Reviewed-by: Erik Hugne <erik.hugne@ericsson.com> Reviewed-by: Jon Maloy <jon.maloy@ericsson.com> Tested-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/name_table.c48
1 files changed, 27 insertions, 21 deletions
diff --git a/net/tipc/name_table.c b/net/tipc/name_table.c
index ba0ee3e8b623..0d61f5826407 100644
--- a/net/tipc/name_table.c
+++ b/net/tipc/name_table.c
@@ -172,18 +172,6 @@ static struct name_seq *tipc_nameseq_create(u32 type, struct hlist_head *seq_hea
172 return nseq; 172 return nseq;
173} 173}
174 174
175/*
176 * nameseq_delete_empty - deletes a name sequence structure if now unused
177 */
178static void nameseq_delete_empty(struct name_seq *seq)
179{
180 if (!seq->first_free && list_empty(&seq->subscriptions)) {
181 hlist_del_init(&seq->ns_list);
182 kfree(seq->sseqs);
183 kfree(seq);
184 }
185}
186
187/** 175/**
188 * nameseq_find_subseq - find sub-sequence (if any) matching a name instance 176 * nameseq_find_subseq - find sub-sequence (if any) matching a name instance
189 * 177 *
@@ -476,6 +464,7 @@ static struct name_seq *nametbl_find_seq(u32 type)
476struct publication *tipc_nametbl_insert_publ(u32 type, u32 lower, u32 upper, 464struct publication *tipc_nametbl_insert_publ(u32 type, u32 lower, u32 upper,
477 u32 scope, u32 node, u32 port, u32 key) 465 u32 scope, u32 node, u32 port, u32 key)
478{ 466{
467 struct publication *publ;
479 struct name_seq *seq = nametbl_find_seq(type); 468 struct name_seq *seq = nametbl_find_seq(type);
480 int index = hash(type); 469 int index = hash(type);
481 470
@@ -492,8 +481,11 @@ struct publication *tipc_nametbl_insert_publ(u32 type, u32 lower, u32 upper,
492 if (!seq) 481 if (!seq)
493 return NULL; 482 return NULL;
494 483
495 return tipc_nameseq_insert_publ(seq, type, lower, upper, 484 spin_lock_bh(&seq->lock);
485 publ = tipc_nameseq_insert_publ(seq, type, lower, upper,
496 scope, node, port, key); 486 scope, node, port, key);
487 spin_unlock_bh(&seq->lock);
488 return publ;
497} 489}
498 490
499struct publication *tipc_nametbl_remove_publ(u32 type, u32 lower, 491struct publication *tipc_nametbl_remove_publ(u32 type, u32 lower,
@@ -505,8 +497,16 @@ struct publication *tipc_nametbl_remove_publ(u32 type, u32 lower,
505 if (!seq) 497 if (!seq)
506 return NULL; 498 return NULL;
507 499
500 spin_lock_bh(&seq->lock);
508 publ = tipc_nameseq_remove_publ(seq, lower, node, ref, key); 501 publ = tipc_nameseq_remove_publ(seq, lower, node, ref, key);
509 nameseq_delete_empty(seq); 502 if (!seq->first_free && list_empty(&seq->subscriptions)) {
503 hlist_del_init(&seq->ns_list);
504 spin_unlock_bh(&seq->lock);
505 kfree(seq->sseqs);
506 kfree(seq);
507 return publ;
508 }
509 spin_unlock_bh(&seq->lock);
510 return publ; 510 return publ;
511} 511}
512 512
@@ -539,10 +539,10 @@ u32 tipc_nametbl_translate(u32 type, u32 instance, u32 *destnode)
539 seq = nametbl_find_seq(type); 539 seq = nametbl_find_seq(type);
540 if (unlikely(!seq)) 540 if (unlikely(!seq))
541 goto not_found; 541 goto not_found;
542 spin_lock_bh(&seq->lock);
542 sseq = nameseq_find_subseq(seq, instance); 543 sseq = nameseq_find_subseq(seq, instance);
543 if (unlikely(!sseq)) 544 if (unlikely(!sseq))
544 goto not_found; 545 goto no_match;
545 spin_lock_bh(&seq->lock);
546 info = sseq->info; 546 info = sseq->info;
547 547
548 /* Closest-First Algorithm */ 548 /* Closest-First Algorithm */
@@ -624,7 +624,6 @@ int tipc_nametbl_mc_translate(u32 type, u32 lower, u32 upper, u32 limit,
624 goto exit; 624 goto exit;
625 625
626 spin_lock_bh(&seq->lock); 626 spin_lock_bh(&seq->lock);
627
628 sseq = seq->sseqs + nameseq_locate_subseq(seq, lower); 627 sseq = seq->sseqs + nameseq_locate_subseq(seq, lower);
629 sseq_stop = seq->sseqs + seq->first_free; 628 sseq_stop = seq->sseqs + seq->first_free;
630 for (; sseq != sseq_stop; sseq++) { 629 for (; sseq != sseq_stop; sseq++) {
@@ -642,7 +641,6 @@ int tipc_nametbl_mc_translate(u32 type, u32 lower, u32 upper, u32 limit,
642 if (info->cluster_list_size != info->node_list_size) 641 if (info->cluster_list_size != info->node_list_size)
643 res = 1; 642 res = 1;
644 } 643 }
645
646 spin_unlock_bh(&seq->lock); 644 spin_unlock_bh(&seq->lock);
647exit: 645exit:
648 read_unlock_bh(&tipc_nametbl_lock); 646 read_unlock_bh(&tipc_nametbl_lock);
@@ -747,8 +745,14 @@ void tipc_nametbl_unsubscribe(struct tipc_subscription *s)
747 if (seq != NULL) { 745 if (seq != NULL) {
748 spin_lock_bh(&seq->lock); 746 spin_lock_bh(&seq->lock);
749 list_del_init(&s->nameseq_list); 747 list_del_init(&s->nameseq_list);
750 spin_unlock_bh(&seq->lock); 748 if (!seq->first_free && list_empty(&seq->subscriptions)) {
751 nameseq_delete_empty(seq); 749 hlist_del_init(&seq->ns_list);
750 spin_unlock_bh(&seq->lock);
751 kfree(seq->sseqs);
752 kfree(seq);
753 } else {
754 spin_unlock_bh(&seq->lock);
755 }
752 } 756 }
753 write_unlock_bh(&tipc_nametbl_lock); 757 write_unlock_bh(&tipc_nametbl_lock);
754} 758}
@@ -964,6 +968,7 @@ static void tipc_purge_publications(struct name_seq *seq)
964 struct sub_seq *sseq; 968 struct sub_seq *sseq;
965 struct name_info *info; 969 struct name_info *info;
966 970
971 spin_lock_bh(&seq->lock);
967 sseq = seq->sseqs; 972 sseq = seq->sseqs;
968 info = sseq->info; 973 info = sseq->info;
969 list_for_each_entry_safe(publ, safe, &info->zone_list, zone_list) { 974 list_for_each_entry_safe(publ, safe, &info->zone_list, zone_list) {
@@ -972,6 +977,8 @@ static void tipc_purge_publications(struct name_seq *seq)
972 kfree(publ); 977 kfree(publ);
973 } 978 }
974 hlist_del_init(&seq->ns_list); 979 hlist_del_init(&seq->ns_list);
980 spin_lock_bh(&seq->lock);
981
975 kfree(seq->sseqs); 982 kfree(seq->sseqs);
976 kfree(seq); 983 kfree(seq);
977} 984}
@@ -1127,7 +1134,6 @@ static int __tipc_nl_seq_list(struct tipc_nl_msg *msg, u32 *last_type,
1127 1134
1128 hlist_for_each_entry_from(seq, ns_list) { 1135 hlist_for_each_entry_from(seq, ns_list) {
1129 spin_lock_bh(&seq->lock); 1136 spin_lock_bh(&seq->lock);
1130
1131 err = __tipc_nl_subseq_list(msg, seq, last_lower, 1137 err = __tipc_nl_subseq_list(msg, seq, last_lower,
1132 last_publ); 1138 last_publ);
1133 1139