linux/net/tipc
Ying Xue fd849b7c41 tipc: fix a race condition of releasing subscriber object
No matter whether a request is inserted into workqueue as a work item
to cancel a subscription or to delete a subscription's subscriber
asynchronously, the work items may be executed in different workers.
As a result, it doesn't mean that one request which is raised prior to
another request is definitely handled before the latter. By contrast,
if the latter request is executed before the former request, below
error may happen:

[  656.183644] BUG: spinlock bad magic on CPU#0, kworker/u8:0/12117
[  656.184487] general protection fault: 0000 [#1] SMP
[  656.185160] Modules linked in: tipc ip6_udp_tunnel udp_tunnel 9pnet_virtio 9p 9pnet virtio_net virtio_pci virtio_ring virtio [last unloaded: ip6_udp_tunnel]
[  656.187003] CPU: 0 PID: 12117 Comm: kworker/u8:0 Not tainted 4.11.0-rc7+ #6
[  656.187920] Hardware name: Bochs Bochs, BIOS Bochs 01/01/2011
[  656.188690] Workqueue: tipc_rcv tipc_recv_work [tipc]
[  656.189371] task: ffff88003f5cec40 task.stack: ffffc90004448000
[  656.190157] RIP: 0010:spin_bug+0xdd/0xf0
[  656.190678] RSP: 0018:ffffc9000444bcb8 EFLAGS: 00010202
[  656.191375] RAX: 0000000000000034 RBX: ffff88003f8d1388 RCX: 0000000000000000
[  656.192321] RDX: ffff88003ba13708 RSI: ffff88003ba0cd08 RDI: ffff88003ba0cd08
[  656.193265] RBP: ffffc9000444bcd0 R08: 0000000000000030 R09: 000000006b6b6b6b
[  656.194208] R10: ffff8800bde3e000 R11: 00000000000001b4 R12: 6b6b6b6b6b6b6b6b
[  656.195157] R13: ffffffff81a3ca64 R14: ffff88003f8d1388 R15: ffff88003f8d13a0
[  656.196101] FS:  0000000000000000(0000) GS:ffff88003ba00000(0000) knlGS:0000000000000000
[  656.197172] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[  656.197935] CR2: 00007f0b3d2e6000 CR3: 000000003ef9e000 CR4: 00000000000006f0
[  656.198873] Call Trace:
[  656.199210]  do_raw_spin_lock+0x66/0xa0
[  656.199735]  _raw_spin_lock_bh+0x19/0x20
[  656.200258]  tipc_subscrb_subscrp_delete+0x28/0xf0 [tipc]
[  656.200990]  tipc_subscrb_rcv_cb+0x45/0x260 [tipc]
[  656.201632]  tipc_receive_from_sock+0xaf/0x100 [tipc]
[  656.202299]  tipc_recv_work+0x2b/0x60 [tipc]
[  656.202872]  process_one_work+0x157/0x420
[  656.203404]  worker_thread+0x69/0x4c0
[  656.203898]  kthread+0x138/0x170
[  656.204328]  ? process_one_work+0x420/0x420
[  656.204889]  ? kthread_create_on_node+0x40/0x40
[  656.205527]  ret_from_fork+0x29/0x40
[  656.206012] Code: 48 8b 0c 25 00 c5 00 00 48 c7 c7 f0 24 a3 81 48 81 c1 f0 05 00 00 65 8b 15 61 ef f5 7e e8 9a 4c 09 00 4d 85 e4 44 8b 4b 08 74 92 <45> 8b 84 24 40 04 00 00 49 8d 8c 24 f0 05 00 00 eb 8d 90 0f 1f
[  656.208504] RIP: spin_bug+0xdd/0xf0 RSP: ffffc9000444bcb8
[  656.209798] ---[ end trace e2a800e6eb0770be ]---

In above scenario, the request of deleting subscriber was performed
earlier than the request of canceling a subscription although the
latter was issued before the former, which means tipc_subscrb_delete()
was called before tipc_subscrp_cancel(). As a result, when
tipc_subscrb_subscrp_delete() called by tipc_subscrp_cancel() was
executed to cancel a subscription, the subscription's subscriber
refcnt had been decreased to 1. After tipc_subscrp_delete() where
the subscriber was freed because its refcnt was decremented to zero,
but the subscriber's lock had to be released, as a consequence, panic
happened.

By contrast, if we increase subscriber's refcnt before
tipc_subscrb_subscrp_delete() is called in tipc_subscrp_cancel(),
the panic issue can be avoided.

Fixes: d094c4d5f5 ("tipc: add subscription refcount to avoid invalid delete")
Reported-by: Parthasarathy Bhuvaragan <parthasarathy.bhuvaragan@ericsson.com>
Signed-off-by: Ying Xue <ying.xue@windriver.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2017-08-22 14:25:02 -07:00
..
addr.c tipc: simplify include dependencies 2015-05-14 12:24:45 -04:00
addr.h tipc: introduce constants for tipc address validation 2016-07-26 14:26:42 -07:00
bcast.c tipc: make replicast a user selectable option 2017-01-20 12:10:17 -05:00
bcast.h tipc: make replicast a user selectable option 2017-01-20 12:10:17 -05:00
bearer.c tipc: accept PACKET_MULTICAST packets 2017-08-14 11:19:25 -07:00
bearer.h tipc: add function for checking broadcast support in bearer 2017-01-20 12:10:15 -05:00
core.c netns: make struct pernet_operations::id unsigned int 2016-11-18 10:59:15 -05:00
core.h netns: make struct pernet_operations::id unsigned int 2016-11-18 10:59:15 -05:00
discover.c tipc: allocate user memory with GFP_KERNEL flag 2017-01-16 13:31:53 -05:00
discover.h tipc: eliminate buffer leak in bearer layer 2016-04-07 17:00:13 -04:00
eth_media.c tipc: make media address offset a common define 2015-02-27 18:18:48 -05:00
ib_media.c tipc: rename media/msg related definitions 2015-02-27 18:18:48 -05:00
Kconfig tipc: add ip/udp media type 2015-03-05 22:08:42 -05:00
link.c netlink: pass extended ACK struct to parsing functions 2017-04-13 13:58:22 -04:00
link.h tipc: transfer broadcast nacks in link state messages 2016-09-02 17:10:24 -07:00
Makefile tipc: add neighbor monitoring framework 2016-06-15 14:06:28 -07:00
monitor.c tipc: improve sanity check for received domain records 2016-11-25 20:06:18 -05:00
monitor.h tipc: dump monitor attributes 2016-07-26 14:26:42 -07:00
msg.c tipc: avoid inheriting msg_non_seq flag when message is returned 2017-08-14 11:20:36 -07:00
msg.h tipc: introduce replicast as transport option for multicast 2017-01-20 12:10:17 -05:00
name_distr.c tipc: allocate user memory with GFP_KERNEL flag 2017-01-16 13:31:53 -05:00
name_distr.h tipc: reduce code dependency between binding table and node layer 2015-11-20 14:06:10 -05:00
name_table.c tipc: adjust the policy of holding subscription kref 2017-03-28 18:03:33 -07:00
name_table.h tipc: add functionality to lookup multicast destination nodes 2017-01-20 12:10:16 -05:00
net.c netlink: pass extended ACK struct where available 2017-04-13 13:58:22 -04:00
net.h tipc: add peer removal functionality 2016-08-18 23:36:07 -07:00
netlink_compat.c tipc: fix use-after-free 2017-08-18 15:59:29 -07:00
netlink.c netlink: pass extended ACK struct to parsing functions 2017-04-13 13:58:22 -04:00
netlink.h tipc: make cluster size threshold for monitoring configurable 2016-07-26 14:26:42 -07:00
node.c tipc: remove premature ESTABLISH FSM event at link synchronization 2017-08-09 22:38:06 -07:00
node.h tipc: make replicast a user selectable option 2017-01-20 12:10:17 -05:00
server.c tipc: fix cleanup at module unload 2017-01-24 16:14:58 -05:00
server.h tipc: fix a race condition leading to subscriber refcnt bug 2016-04-14 16:46:46 -04:00
socket.c net: convert sock.sk_refcnt from atomic_t to refcount_t 2017-07-01 07:39:08 -07:00
socket.h tipc: redesign connection-level flow control 2016-05-03 15:51:16 -04:00
subscr.c tipc: fix a race condition of releasing subscriber object 2017-08-22 14:25:02 -07:00
subscr.h tipc: adjust the policy of holding subscription kref 2017-03-28 18:03:33 -07:00
sysctl.c tipc: add name distributor resiliency queue 2014-09-01 17:51:48 -07:00
udp_media.c netlink: pass extended ACK struct to parsing functions 2017-04-13 13:58:22 -04:00
udp_media.h tipc: add UDP remoteip dump to netlink API 2016-08-26 21:38:41 -07:00