tipc: protect handler_enabled variable with qitem_lock spin lock

'handler_enabled' is a global flag indicating whether the TIPC
signal handling service is enabled or not. The lack of lock
protection for this flag incurs a risk for contention, so that
a tipc_k_signal() call might queue a signal handler to a destroyed
signal queue, with unpredictable results. To correct this, we let
the already existing 'qitem_lock' protect the flag, as it already
does with the queue itself. This way, we ensure that the flag
always is consistent across all cores.

Signed-off-by: Ying Xue <ying.xue@windriver.com>
Reviewed-by: Paul Gortmaker <paul.gortmaker@windriver.com>
Signed-off-by: Jon Maloy <jon.maloy@ericsson.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
diff --git a/net/tipc/handler.c b/net/tipc/handler.c
index b36f0fc..e4bc8a2 100644
--- a/net/tipc/handler.c
+++ b/net/tipc/handler.c
@@ -56,12 +56,13 @@
 {
 	struct queue_item *item;
 
+	spin_lock_bh(&qitem_lock);
 	if (!handler_enabled) {
 		pr_err("Signal request ignored by handler\n");
+		spin_unlock_bh(&qitem_lock);
 		return -ENOPROTOOPT;
 	}
 
-	spin_lock_bh(&qitem_lock);
 	item = kmem_cache_alloc(tipc_queue_item_cache, GFP_ATOMIC);
 	if (!item) {
 		pr_err("Signal queue out of memory\n");
@@ -112,10 +113,14 @@
 	struct list_head *l, *n;
 	struct queue_item *item;
 
-	if (!handler_enabled)
+	spin_lock_bh(&qitem_lock);
+	if (!handler_enabled) {
+		spin_unlock_bh(&qitem_lock);
 		return;
-
+	}
 	handler_enabled = 0;
+	spin_unlock_bh(&qitem_lock);
+
 	tasklet_kill(&tipc_tasklet);
 
 	spin_lock_bh(&qitem_lock);