From f3ad288c56d21e3b8ec77e13ab9aa06dbbfa3577 Mon Sep 17 00:00:00 2001 From: Parthasarathy Bhuvaragan Date: Tue, 2 Feb 2016 10:52:15 +0100 Subject: tipc: protect tipc_subscrb_get() with subscriber spin lock Until now, during subscription creation the mod_time() & tipc_subscrb_get() are called after releasing the subscriber spin lock. In a SMP system when performing a subscription creation, if the subscription timeout occurs simultaneously (the timer is scheduled to run on another CPU) then the timer thread might decrement the subscribers refcount before the create thread increments the refcount. This can be simulated by creating subscription with timeout=0 and sometimes the timeout occurs before the create request is complete. This leads to the following message: [30.702949] BUG: spinlock bad magic on CPU#1, kworker/u8:3/87 [30.703834] general protection fault: 0000 [#1] SMP [30.704826] CPU: 1 PID: 87 Comm: kworker/u8:3 Not tainted 4.4.0-rc8+ #18 [30.704826] Workqueue: tipc_rcv tipc_recv_work [tipc] [30.704826] task: ffff88003f878600 ti: ffff88003fae0000 task.ti: ffff88003fae0000 [30.704826] RIP: 0010:[] [] spin_dump+0x5c/0xe0 [...] [30.704826] Call Trace: [30.704826] [] spin_bug+0x26/0x30 [30.704826] [] do_raw_spin_lock+0xe5/0x120 [30.704826] [] _raw_spin_lock_bh+0x19/0x20 [30.704826] [] tipc_subscrb_rcv_cb+0x1d0/0x330 [tipc] [30.704826] [] tipc_receive_from_sock+0xc1/0x150 [tipc] [30.704826] [] tipc_recv_work+0x3f/0x80 [tipc] [30.704826] [] process_one_work+0x149/0x3c0 [30.704826] [] worker_thread+0x66/0x460 [30.704826] [] ? process_one_work+0x3c0/0x3c0 [30.704826] [] ? process_one_work+0x3c0/0x3c0 [30.704826] [] kthread+0xed/0x110 [30.704826] [] ? kthread_create_on_node+0x190/0x190 [30.704826] [] ret_from_fork+0x3f/0x70 In this commit, 1. we remove the check for the return code for mod_timer() 2. we protect tipc_subscrb_get() using the subscriber spin lock. We increment the subscriber's refcount as soon as we add the subscription to subscriber's subscription list. Acked-by: Ying Xue Reviewed-by: Jon Maloy Signed-off-by: Parthasarathy Bhuvaragan Signed-off-by: David S. Miller --- net/tipc/subscr.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/tipc/subscr.c b/net/tipc/subscr.c index e4ebbc161e42..7d226ecb0490 100644 --- a/net/tipc/subscr.c +++ b/net/tipc/subscr.c @@ -284,13 +284,13 @@ static void tipc_subscrp_subscribe(struct net *net, struct tipc_subscr *s, spin_lock_bh(&subscriber->lock); list_add(&sub->subscrp_list, &subscriber->subscrp_list); + tipc_subscrb_get(subscriber); sub->subscriber = subscriber; tipc_nametbl_subscribe(sub); spin_unlock_bh(&subscriber->lock); timeout = htohl(sub->evt.s.timeout, swap); - if (!mod_timer(&sub->timer, jiffies + msecs_to_jiffies(timeout))) - tipc_subscrb_get(subscriber); + mod_timer(&sub->timer, jiffies + msecs_to_jiffies(timeout)); } /* Handle one termination request for the subscriber */ -- cgit v1.2.3