linux/net/tipc
Ying Xue 37436d9c0e tipc: fix an interrupt unsafe locking scenario
Commit 9faa89d4ed ("tipc: make function tipc_net_finalize() thread
safe") tries to make it thread safe to set node address, so it uses
node_list_lock lock to serialize the whole process of setting node
address in tipc_net_finalize(). But it causes the following interrupt
unsafe locking scenario:

       CPU0                    CPU1
       ----                    ----
  rht_deferred_worker()
  rhashtable_rehash_table()
  lock(&(&ht->lock)->rlock)
			       tipc_nl_compat_doit()
                               tipc_net_finalize()
                               local_irq_disable();
                               lock(&(&tn->node_list_lock)->rlock);
                               tipc_sk_reinit()
                               rhashtable_walk_enter()
                               lock(&(&ht->lock)->rlock);
  <Interrupt>
  tipc_disc_rcv()
  tipc_node_check_dest()
  tipc_node_create()
  lock(&(&tn->node_list_lock)->rlock);

 *** DEADLOCK ***

When rhashtable_rehash_table() holds ht->lock on CPU0, it doesn't
disable BH. So if an interrupt happens after the lock, it can create
an inverse lock ordering between ht->lock and tn->node_list_lock. As
a consequence, deadlock might happen.

The reason causing the inverse lock ordering scenario above is because
the initial purpose of node_list_lock is not designed to do the
serialization of node address setting.

As cmpxchg() can guarantee CAS (compare-and-swap) process is atomic,
we use it to replace node_list_lock to ensure setting node address can
be atomically finished. It turns out the potential deadlock can be
avoided as well.

Fixes: 9faa89d4ed ("tipc: make function tipc_net_finalize() thread safe")
Signed-off-by: Ying Xue <ying.xue@windriver.com>
Acked-by: Jon Maloy <maloy@donjonn.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2018-08-07 13:15:35 -07:00
..
addr.c tipc: handle collisions of 32-bit node address hash values 2018-03-23 13:12:18 -04:00
addr.h tipc: add 128-bit node identifier 2018-03-23 13:12:18 -04:00
bcast.c tipc: bcast: use true and false for boolean values 2018-03-07 12:18:00 -05:00
bcast.h tipc: make replicast a user selectable option 2017-01-20 12:10:17 -05:00
bearer.c tipc: confgiure and apply UDP bearer MTU on running links 2018-04-20 11:04:05 -04:00
bearer.h tipc: implement configuration of UDP media MTU 2018-04-20 11:04:05 -04:00
core.c net: Drop pernet_operations::async 2018-03-27 13:18:09 -04:00
core.h tipc: replace name table service range array with rb tree 2018-03-31 22:19:52 -04:00
diag.c tipc: use the right skb in tipc_sk_fill_sock_diag() 2018-04-08 12:34:29 -04:00
discover.c tipc: fix correct setting of message type in second discoverer 2018-07-07 19:49:01 +09:00
discover.h tipc: some cleanups in the file discover.c 2018-03-23 13:12:17 -04:00
eth_media.c tipc: make media address offset a common define 2015-02-27 18:18:48 -05:00
group.c Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net 2018-03-06 01:20:46 -05:00
group.h tipc: fix race between poll() and setsockopt() 2018-01-19 15:12:21 -05:00
ib_media.c tipc: rename media/msg related definitions 2015-02-27 18:18:48 -05:00
Kconfig tipc: implement socket diagnostics for AF_TIPC 2018-03-22 14:43:35 -04:00
link.c tipc: avoid possible string overflow 2018-03-31 22:19:52 -04:00
link.h tipc: handle collisions of 32-bit node address hash values 2018-03-23 13:12:18 -04:00
Makefile tipc: implement socket diagnostics for AF_TIPC 2018-03-22 14:43:35 -04:00
monitor.c tipc: fix infinite loop when dumping link monitor summary 2018-04-18 13:48:43 -04:00
monitor.h tipc: dump monitor attributes 2016-07-26 14:26:42 -07:00
msg.c tipc: obsolete TIPC_ZONE_SCOPE 2018-03-17 17:11:46 -04:00
msg.h tipc: handle collisions of 32-bit node address hash values 2018-03-23 13:12:18 -04:00
name_distr.c tipc: permit overlapping service ranges in name table 2018-03-31 22:19:52 -04:00
name_distr.h tipc: permit overlapping service ranges in name table 2018-03-31 22:19:52 -04:00
name_table.c tipc: clean up removal of binding table items 2018-05-10 15:25:45 -04:00
name_table.h tipc: fix unbalanced reference counter 2018-04-12 21:46:10 -04:00
net.c tipc: fix an interrupt unsafe locking scenario 2018-08-07 13:15:35 -07:00
net.h tipc: obtain node identity from interface by default 2018-03-23 13:12:18 -04:00
netlink_compat.c treewide: kmalloc() -> kmalloc_array() 2018-06-12 16:19:22 -07:00
netlink.c tipc: fix possible crash in __tipc_nl_net_set() 2018-04-16 18:08:18 -04:00
netlink.h tipc: make cluster size threshold for monitoring configurable 2016-07-26 14:26:42 -07:00
node.c tipc: fix wrong return value from function tipc_node_try_addr() 2018-07-07 19:49:01 +09:00
node.h tipc: introduce ioctl for fetching node identity 2018-04-27 11:05:41 -04:00
socket.c Revert changes to convert to ->poll_mask() and aio IOCB_CMD_POLL 2018-06-28 10:40:47 -07:00
socket.h tipc: use the right skb in tipc_sk_fill_sock_diag() 2018-04-08 12:34:29 -04:00
subscr.c tipc: fix unbalanced reference counter 2018-04-12 21:46:10 -04:00
subscr.h tipc: replace name table service range array with rb tree 2018-03-31 22:19:52 -04:00
sysctl.c tipc: add name distributor resiliency queue 2014-09-01 17:51:48 -07:00
topsrv.c tipc: don't call sock_release() in atomic context 2018-02-19 14:38:50 -05:00
topsrv.h tipc: rename tipc_server to tipc_topsrv 2018-02-16 15:26:34 -05:00
udp_media.c tipc: set default MTU for UDP media 2018-04-20 11:04:05 -04:00
udp_media.h tipc: implement configuration of UDP media MTU 2018-04-20 11:04:05 -04:00