Skip to content

Commit 557d054

Browse files
ying-xuedavem330
authored andcommitted
tipc: fix nametbl deadlock at tipc_nametbl_unsubscribe
Until now, tipc_nametbl_unsubscribe() is called at subscriptions reference count cleanup. Usually the subscriptions cleanup is called at subscription timeout or at subscription cancel or at subscriber delete. We have ignored the possibility of this being called from other locations, which causes deadlock as we try to grab the tn->nametbl_lock while holding it already. CPU1: CPU2: ---------- ---------------- tipc_nametbl_publish spin_lock_bh(&tn->nametbl_lock) tipc_nametbl_insert_publ tipc_nameseq_insert_publ tipc_subscrp_report_overlap tipc_subscrp_get tipc_subscrp_send_event tipc_close_conn tipc_subscrb_release_cb tipc_subscrb_delete tipc_subscrp_put tipc_subscrp_put tipc_subscrp_kref_release tipc_nametbl_unsubscribe spin_lock_bh(&tn->nametbl_lock) <<grab nametbl_lock again>> CPU1: CPU2: ---------- ---------------- tipc_nametbl_stop spin_lock_bh(&tn->nametbl_lock) tipc_purge_publications tipc_nameseq_remove_publ tipc_subscrp_report_overlap tipc_subscrp_get tipc_subscrp_send_event tipc_close_conn tipc_subscrb_release_cb tipc_subscrb_delete tipc_subscrp_put tipc_subscrp_put tipc_subscrp_kref_release tipc_nametbl_unsubscribe spin_lock_bh(&tn->nametbl_lock) <<grab nametbl_lock again>> In this commit, we advance the calling of tipc_nametbl_unsubscribe() from the refcount cleanup to the intended callers. Fixes: d094c4d ("tipc: add subscription refcount to avoid invalid delete") Reported-by: John Thompson <[email protected]> Acked-by: Jon Maloy <[email protected]> Signed-off-by: Ying Xue <[email protected]> Signed-off-by: Parthasarathy Bhuvaragan <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 5819477 commit 557d054

File tree

1 file changed

+6
-1
lines changed

1 file changed

+6
-1
lines changed

net/tipc/subscr.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,11 @@ void tipc_subscrp_report_overlap(struct tipc_subscription *sub, u32 found_lower,
141141
static void tipc_subscrp_timeout(unsigned long data)
142142
{
143143
struct tipc_subscription *sub = (struct tipc_subscription *)data;
144+
struct tipc_subscriber *subscriber = sub->subscriber;
145+
146+
spin_lock_bh(&subscriber->lock);
147+
tipc_nametbl_unsubscribe(sub);
148+
spin_unlock_bh(&subscriber->lock);
144149

145150
/* Notify subscriber of timeout */
146151
tipc_subscrp_send_event(sub, sub->evt.s.seq.lower, sub->evt.s.seq.upper,
@@ -173,7 +178,6 @@ static void tipc_subscrp_kref_release(struct kref *kref)
173178
struct tipc_subscriber *subscriber = sub->subscriber;
174179

175180
spin_lock_bh(&subscriber->lock);
176-
tipc_nametbl_unsubscribe(sub);
177181
list_del(&sub->subscrp_list);
178182
atomic_dec(&tn->subscription_count);
179183
spin_unlock_bh(&subscriber->lock);
@@ -205,6 +209,7 @@ static void tipc_subscrb_subscrp_delete(struct tipc_subscriber *subscriber,
205209
if (s && memcmp(s, &sub->evt.s, sizeof(struct tipc_subscr)))
206210
continue;
207211

212+
tipc_nametbl_unsubscribe(sub);
208213
tipc_subscrp_get(sub);
209214
spin_unlock_bh(&subscriber->lock);
210215
tipc_subscrp_delete(sub);

0 commit comments

Comments
 (0)