From: Dave Marquardt <[email protected]> ibmvfc_free_queue() unconditionally calls dma_unmap_single() before freeing the queue page, but only guards free_page() behind a queue->msgs.handle check. If ibmvfc_alloc_queue() fails before the DMA mapping is established (e.g. get_zeroed_page() fails or ibmvfc_init_event_pool() fails), msgs.handle and msg_token are both zero/NULL. Calling dma_unmap_single() with address 0 is unsafe on many architectures.
Guard dma_unmap_single() and free_page() together under the existing msgs.handle check so ibmvfc_free_queue() is safe to call on a partially or never-initialized queue. Signed-off-by: Dave Marquardt <[email protected]> --- drivers/scsi/ibmvscsi/ibmvfc-core.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/scsi/ibmvscsi/ibmvfc-core.c b/drivers/scsi/ibmvscsi/ibmvfc-core.c index f0502d748210..b63b341efb07 100644 --- a/drivers/scsi/ibmvscsi/ibmvfc-core.c +++ b/drivers/scsi/ibmvscsi/ibmvfc-core.c @@ -913,9 +913,11 @@ static void ibmvfc_free_queue(struct ibmvfc_host *vhost, { struct device *dev = vhost->dev; - dma_unmap_single(dev, queue->msg_token, PAGE_SIZE, DMA_BIDIRECTIONAL); - free_page((unsigned long)queue->msgs.handle); - queue->msgs.handle = NULL; + if (queue->msgs.handle) { + dma_unmap_single(dev, queue->msg_token, PAGE_SIZE, DMA_BIDIRECTIONAL); + free_page((unsigned long)queue->msgs.handle); + queue->msgs.handle = NULL; + } ibmvfc_free_event_pool(vhost, queue); } -- 2.56.0
