Skip to content

Commit fb9962f

Browse files
ying-xuedavem330
authored andcommitted
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>
1 parent 38622f4 commit fb9962f

File tree

1 file changed

+27
-21
lines changed

1 file changed

+27
-21
lines changed

net/tipc/name_table.c

Lines changed: 27 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -172,18 +172,6 @@ static struct name_seq *tipc_nameseq_create(u32 type, struct hlist_head *seq_hea
172172
return nseq;
173173
}
174174

175-
/*
176-
* nameseq_delete_empty - deletes a name sequence structure if now unused
177-
*/
178-
static 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-
187175
/**
188176
* nameseq_find_subseq - find sub-sequence (if any) matching a name instance
189177
*
@@ -476,6 +464,7 @@ static struct name_seq *nametbl_find_seq(u32 type)
476464
struct publication *tipc_nametbl_insert_publ(u32 type, u32 lower, u32 upper,
477465
u32 scope, u32 node, u32 port, u32 key)
478466
{
467+
struct publication *publ;
479468
struct name_seq *seq = nametbl_find_seq(type);
480469
int index = hash(type);
481470

@@ -492,8 +481,11 @@ struct publication *tipc_nametbl_insert_publ(u32 type, u32 lower, u32 upper,
492481
if (!seq)
493482
return NULL;
494483

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,
496486
scope, node, port, key);
487+
spin_unlock_bh(&seq->lock);
488+
return publ;
497489
}
498490

499491
struct publication *tipc_nametbl_remove_publ(u32 type, u32 lower,
@@ -505,8 +497,16 @@ struct publication *tipc_nametbl_remove_publ(u32 type, u32 lower,
505497
if (!seq)
506498
return NULL;
507499

500+
spin_lock_bh(&seq->lock);
508501
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);
510510
return publ;
511511
}
512512

@@ -539,10 +539,10 @@ u32 tipc_nametbl_translate(u32 type, u32 instance, u32 *destnode)
539539
seq = nametbl_find_seq(type);
540540
if (unlikely(!seq))
541541
goto not_found;
542+
spin_lock_bh(&seq->lock);
542543
sseq = nameseq_find_subseq(seq, instance);
543544
if (unlikely(!sseq))
544-
goto not_found;
545-
spin_lock_bh(&seq->lock);
545+
goto no_match;
546546
info = sseq->info;
547547

548548
/* Closest-First Algorithm */
@@ -624,7 +624,6 @@ int tipc_nametbl_mc_translate(u32 type, u32 lower, u32 upper, u32 limit,
624624
goto exit;
625625

626626
spin_lock_bh(&seq->lock);
627-
628627
sseq = seq->sseqs + nameseq_locate_subseq(seq, lower);
629628
sseq_stop = seq->sseqs + seq->first_free;
630629
for (; sseq != sseq_stop; sseq++) {
@@ -642,7 +641,6 @@ int tipc_nametbl_mc_translate(u32 type, u32 lower, u32 upper, u32 limit,
642641
if (info->cluster_list_size != info->node_list_size)
643642
res = 1;
644643
}
645-
646644
spin_unlock_bh(&seq->lock);
647645
exit:
648646
read_unlock_bh(&tipc_nametbl_lock);
@@ -747,8 +745,14 @@ void tipc_nametbl_unsubscribe(struct tipc_subscription *s)
747745
if (seq != NULL) {
748746
spin_lock_bh(&seq->lock);
749747
list_del_init(&s->nameseq_list);
750-
spin_unlock_bh(&seq->lock);
751-
nameseq_delete_empty(seq);
748+
if (!seq->first_free && list_empty(&seq->subscriptions)) {
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+
}
752756
}
753757
write_unlock_bh(&tipc_nametbl_lock);
754758
}
@@ -964,6 +968,7 @@ static void tipc_purge_publications(struct name_seq *seq)
964968
struct sub_seq *sseq;
965969
struct name_info *info;
966970

971+
spin_lock_bh(&seq->lock);
967972
sseq = seq->sseqs;
968973
info = sseq->info;
969974
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)
972977
kfree(publ);
973978
}
974979
hlist_del_init(&seq->ns_list);
980+
spin_lock_bh(&seq->lock);
981+
975982
kfree(seq->sseqs);
976983
kfree(seq);
977984
}
@@ -1127,7 +1134,6 @@ static int __tipc_nl_seq_list(struct tipc_nl_msg *msg, u32 *last_type,
11271134

11281135
hlist_for_each_entry_from(seq, ns_list) {
11291136
spin_lock_bh(&seq->lock);
1130-
11311137
err = __tipc_nl_subseq_list(msg, seq, last_lower,
11321138
last_publ);
11331139

0 commit comments

Comments
 (0)