Thread (21 messages) 21 messages, 1 author, 27d ago

[PATCH 17/20] scsi: ibmvfc: fix TOCTOU race in ibmvfc_nvme_create_queue() on adapter removal

flat view
DORMANTno replies SUPERSEDED

From: Tyrel Datwyler <tyreld@linux.ibm.com>
Date: 2026-09-16 23:09:54
Also in: linux-scsi, lkml
Subsystem: ibm power virtual fc device drivers, linux for powerpc (32-bit and 64-bit), scsi subsystem, the rest · Maintainers: Tyrel Datwyler, Madhavan Srinivasan, "James E.J. Bottomley", "Martin K. Petersen", Linus Torvalds

Revision v1 of 2 in this series.

Revisions (2)
  1. v1 current
  2. v2 [diff vs current]
ibmvfc_remove() called ibmvfc_release_sub_crqs() before
ibmvfc_nvme_unregister().  ibmvfc_release_sub_crqs() frees the
nvme_scrqs.scrqs array and sets active_queues to 0, but the nvme-fc
transport is still live at that point and can call back into
ibmvfc_nvme_create_queue().  That callback reads active_queues and
dereferences scrqs without any lock, so the window between the guard
check and the actual use can race with the teardown, leading to:

  - divide-by-zero in '(qidx - 1) % vhost->nvme_scrqs.active_queues'
    when active_queues has been zeroed concurrently, and
  - NULL pointer dereference on 'vhost->nvme_scrqs.scrqs[qhandle->index]'
    when scrqs has been freed and set to NULL concurrently.

ibmvfc_nvme_unregister() already calls nvme_fc_unregister_localport()
followed by wait_for_completion(), which blocks until the transport has
fully quiesced all queue operations.  It just needs to happen before the
sub-CRQ memory is released.

Move ibmvfc_nvme_unregister() before ibmvfc_release_sub_crqs() in
ibmvfc_remove() so the transport is quiesced before the sub-CRQ arrays
are freed.  The reset path (ibmvfc_reset_crq) is unaffected: it only
deregisters sub-CRQs at the hypervisor level and never frees them, so
active_queues and scrqs remain valid across a reset.

Fixes: 186f72e38029 ("scsi: ibmvfc: implement LLDD callbacks for mapping nvme-fc queues")
Signed-off-by: Tyrel Datwyler <tyreld@linux.ibm.com>
---
 drivers/scsi/ibmvscsi/ibmvfc-core.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/drivers/scsi/ibmvscsi/ibmvfc-core.c b/drivers/scsi/ibmvscsi/ibmvfc-core.c
index 7af1867b69c5..93189692191e 100644
--- a/drivers/scsi/ibmvscsi/ibmvfc-core.c
+++ b/drivers/scsi/ibmvscsi/ibmvfc-core.c
@@ -6992,11 +6992,10 @@ static void ibmvfc_remove(struct vio_dev *vdev)
 	list_splice_init(&vhost->purge, &purge);
 	spin_unlock_irqrestore(&vhost->host->host_lock, flags);
 	ibmvfc_complete_purge(&purge);
+	ibmvfc_nvme_unregister(vhost);
 	ibmvfc_release_sub_crqs(vhost);
 	ibmvfc_release_crq_queue(vhost);
 
-	ibmvfc_nvme_unregister(vhost);
-
 	ibmvfc_free_mem(vhost);
 	spin_lock(&ibmvfc_driver_lock);
 	list_del(&vhost->queue);
-- 
2.55.0

Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help