RDMA/srpt: Fix a use-after-free in the channel release code
Subsystems (3)
A message that is not in the archive (sent off-list or not yet received): [email protected]
Bart Van Assche
maintainerPATCH v2 9/15 RDMA/srpt: Fix a use-after-free in the channel release code
This patch avoids that KASAN sporadically reports the following:
BUG: KASAN: use-after-free in rxe_run_task+0x1e/0x60 [rdma_rxe] Read of size 1 at addr ffff88801c50d8f4 by task check/24830 CPU: 4 PID: 24830 Comm: check Not tainted 4.20.0-rc6-dbg+ #3 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.10.2-1 04/01/2014 Call Trace: dump_stack+0x86/0xca print_address_description+0x71/0x239 kasan_report.cold.5+0x242/0x301 __asan_load1+0x47/0x50 rxe_run_task+0x1e/0x60 [rdma_rxe] rxe_post_send+0x4bd/0x8d0 [rdma_rxe] srpt_zerolength_write+0xe1/0x160 [ib_srpt] srpt_close_ch+0x8b/0xe0 [ib_srpt] srpt_set_enabled+0xe7/0x150 [ib_srpt] srpt_tpg_enable_store+0xc0/0x100 [ib_srpt] configfs_write_file+0x157/0x1d0 __vfs_write+0xd7/0x3d0 vfs_write+0x102/0x290 ksys_write+0xab/0x130 __x64_sys_write+0x43/0x50 do_syscall_64+0x71/0x210 entry_SYSCALL_64_after_hwframe+0x49/0xbe Allocated by task 13856: save_stack+0x43/0xd0 kasan_kmalloc+0xc7/0xe0 kasan_slab_alloc+0x11/0x20 kmem_cache_alloc+0x105/0x320 rxe_alloc+0xff/0x1f0 [rdma_rxe] rxe_create_qp+0x9f/0x160 [rdma_rxe] ib_create_qp+0xf5/0x690 [ib_core] rdma_create_qp+0x6a/0x140 [rdma_cm] srpt_cm_req_recv.cold.59+0x1588/0x237b [ib_srpt] srpt_rdma_cm_req_recv.isra.35+0x1d5/0x220 [ib_srpt] srpt_rdma_cm_handler+0x6f/0x100 [ib_srpt] cma_listen_handler+0x59/0x60 [rdma_cm] cma_ib_req_handler+0xd5b/0x2570 [rdma_cm] cm_process_work+0x2e/0x110 [ib_cm] cm_work_handler+0x2aae/0x502b [ib_cm] process_one_work+0x481/0x9e0 worker_thread+0x67/0x5b0 kthread+0x1cf/0x1f0 ret_from_fork+0x24/0x30 Freed by task 3440: save_stack+0x43/0xd0 __kasan_slab_free+0x139/0x190 kasan_slab_free+0xe/0x10 kmem_cache_free+0xbc/0x330 rxe_elem_release+0x66/0xe0 [rdma_rxe] rxe_destroy_qp+0x3f/0x50 [rdma_rxe] ib_destroy_qp+0x140/0x360 [ib_core] srpt_release_channel_work+0xdc/0x310 [ib_srpt] process_one_work+0x481/0x9e0 worker_thread+0x67/0x5b0 kthread+0x1cf/0x1f0 ret_from_fork+0x24/0x30
Cc Sergey Gorenko <[email protected]>
Cc Max Gurtovoy <[email protected]>
Cc Laurence Oberman <[email protected]>
Cc <[email protected]>
Signed-off-by Bart Van Assche <[email protected]>
--- drivers/infiniband/ulp/srpt/ib_srpt.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-)
drivers/infiniband/ulp/srpt/ib_srpt.c +13 -5
@@ -2010,6 +2010,14 @@ static void srpt_free_ch(struct kref *kref)kfree_rcu (ch, rcu); } +/* +* Shut down the SCSI target session, tell the connection manager to +* disconnect the associated RDMA channel, transition the QP to the error +* state and remove the channel from the channel list. This function is +* typically called from inside srpt_zerolength_write_done(). Concurrent +* srpt_zerolength_write() calls from inside srpt_close_ch() are possible +* as long as the channel is on sport->nexus_list. +*/ static void srpt_release_channel_work (struct work_struct *w) {struct srpt_rdma_ch *ch;
@@ -2037,6 +2045,11 @@ static void srpt_release_channel_work(struct work_struct *w)else ib_destroy_cm_id (ch->ib_cm.cm_id); + sport = ch->sport; +mutex_lock (&sport->mutex); +list_del_rcu (&ch->list); +mutex_unlock (&sport->mutex); +srpt_destroy_ch_ib (ch); srpt_free_ioctx_ring((struct srpt_ioctx **)ch->ioctx_ring,
@@ -2047,11 +2060,6 @@ static void srpt_release_channel_work(struct work_struct *w) sdev, ch->rq_size, srp_max_req_size, DMA_FROM_DEVICE); - sport = ch->sport; -mutex_lock (&sport->mutex); -list_del_rcu (&ch->list); -mutex_unlock (&sport->mutex); -wake_up (&sport->ch_releaseQ);kref_put (&ch->kref, srpt_free_ch);
Signature · 1 line
2.20.0.405.gbc1bbc6f85-goog