Skip to content

Commit

Permalink
tipc: ensure all name sequences are properly protected with its lock
Browse files Browse the repository at this point in the history
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 <[email protected]>
Reviewed-by: Erik Hugne <[email protected]>
Reviewed-by: Jon Maloy <[email protected]>
Tested-by: Erik Hugne <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
  • Loading branch information
ying-xue authored and davem330 committed Dec 9, 2014
1 parent 38622f4 commit fb9962f
Showing 1 changed file with 27 additions and 21 deletions.
48 changes: 27 additions & 21 deletions net/tipc/name_table.c
Original file line number Diff line number Diff line change
Expand Up @@ -172,18 +172,6 @@ static struct name_seq *tipc_nameseq_create(u32 type, struct hlist_head *seq_hea
return nseq;
}

/*
* nameseq_delete_empty - deletes a name sequence structure if now unused
*/
static void nameseq_delete_empty(struct name_seq *seq)
{
if (!seq->first_free && list_empty(&seq->subscriptions)) {
hlist_del_init(&seq->ns_list);
kfree(seq->sseqs);
kfree(seq);
}
}

/**
* nameseq_find_subseq - find sub-sequence (if any) matching a name instance
*
Expand Down Expand Up @@ -476,6 +464,7 @@ static struct name_seq *nametbl_find_seq(u32 type)
struct publication *tipc_nametbl_insert_publ(u32 type, u32 lower, u32 upper,
u32 scope, u32 node, u32 port, u32 key)
{
struct publication *publ;
struct name_seq *seq = nametbl_find_seq(type);
int index = hash(type);

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

return tipc_nameseq_insert_publ(seq, type, lower, upper,
spin_lock_bh(&seq->lock);
publ = tipc_nameseq_insert_publ(seq, type, lower, upper,
scope, node, port, key);
spin_unlock_bh(&seq->lock);
return publ;
}

struct publication *tipc_nametbl_remove_publ(u32 type, u32 lower,
Expand All @@ -505,8 +497,16 @@ struct publication *tipc_nametbl_remove_publ(u32 type, u32 lower,
if (!seq)
return NULL;

spin_lock_bh(&seq->lock);
publ = tipc_nameseq_remove_publ(seq, lower, node, ref, key);
nameseq_delete_empty(seq);
if (!seq->first_free && list_empty(&seq->subscriptions)) {
hlist_del_init(&seq->ns_list);
spin_unlock_bh(&seq->lock);
kfree(seq->sseqs);
kfree(seq);
return publ;
}
spin_unlock_bh(&seq->lock);
return publ;
}

Expand Down Expand Up @@ -539,10 +539,10 @@ u32 tipc_nametbl_translate(u32 type, u32 instance, u32 *destnode)
seq = nametbl_find_seq(type);
if (unlikely(!seq))
goto not_found;
spin_lock_bh(&seq->lock);
sseq = nameseq_find_subseq(seq, instance);
if (unlikely(!sseq))
goto not_found;
spin_lock_bh(&seq->lock);
goto no_match;
info = sseq->info;

/* Closest-First Algorithm */
Expand Down Expand Up @@ -624,7 +624,6 @@ int tipc_nametbl_mc_translate(u32 type, u32 lower, u32 upper, u32 limit,
goto exit;

spin_lock_bh(&seq->lock);

sseq = seq->sseqs + nameseq_locate_subseq(seq, lower);
sseq_stop = seq->sseqs + seq->first_free;
for (; sseq != sseq_stop; sseq++) {
Expand All @@ -642,7 +641,6 @@ int tipc_nametbl_mc_translate(u32 type, u32 lower, u32 upper, u32 limit,
if (info->cluster_list_size != info->node_list_size)
res = 1;
}

spin_unlock_bh(&seq->lock);
exit:
read_unlock_bh(&tipc_nametbl_lock);
Expand Down Expand Up @@ -747,8 +745,14 @@ void tipc_nametbl_unsubscribe(struct tipc_subscription *s)
if (seq != NULL) {
spin_lock_bh(&seq->lock);
list_del_init(&s->nameseq_list);
spin_unlock_bh(&seq->lock);
nameseq_delete_empty(seq);
if (!seq->first_free && list_empty(&seq->subscriptions)) {
hlist_del_init(&seq->ns_list);
spin_unlock_bh(&seq->lock);
kfree(seq->sseqs);
kfree(seq);
} else {
spin_unlock_bh(&seq->lock);
}
}
write_unlock_bh(&tipc_nametbl_lock);
}
Expand Down Expand Up @@ -964,6 +968,7 @@ static void tipc_purge_publications(struct name_seq *seq)
struct sub_seq *sseq;
struct name_info *info;

spin_lock_bh(&seq->lock);
sseq = seq->sseqs;
info = sseq->info;
list_for_each_entry_safe(publ, safe, &info->zone_list, zone_list) {
Expand All @@ -972,6 +977,8 @@ static void tipc_purge_publications(struct name_seq *seq)
kfree(publ);
}
hlist_del_init(&seq->ns_list);
spin_lock_bh(&seq->lock);

kfree(seq->sseqs);
kfree(seq);
}
Expand Down Expand Up @@ -1127,7 +1134,6 @@ static int __tipc_nl_seq_list(struct tipc_nl_msg *msg, u32 *last_type,

hlist_for_each_entry_from(seq, ns_list) {
spin_lock_bh(&seq->lock);

err = __tipc_nl_subseq_list(msg, seq, last_lower,
last_publ);

Expand Down

0 comments on commit fb9962f

Please sign in to comment.