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



Reply via email to