scsi: qla2xxx: Fix use-after-free issues in qla2xxx_qpair_sp_free_dma()
authorBart Van Assche <bvanassche@acm.org>
Wed, 17 Apr 2019 21:44:25 +0000 (14:44 -0700)
committerMartin K. Petersen <martin.petersen@oracle.com>
Mon, 29 Apr 2019 21:24:50 +0000 (17:24 -0400)
The current order for freeing memory is as follows:
- struct crc_context itself.
- struct crc_context member pointers.

Change the freeing order into the following:
- struct crc_context member pointers.
- struct crc_context itself.

Detected by Coverity.

Cc: Himanshu Madhani <hmadhani@marvell.com>
Cc: Giridhar Malavali <gmalavali@marvell.com>
Fixes: 50b812755e97 ("scsi: qla2xxx: Fix DMA error when the DIF sg buffer crosses 4GB boundary") # v5.1-rc1.
Fixes: d74595278f4a ("scsi: qla2xxx: Add multiple queue pair functionality.") # v4.10.
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
Acked-by: Himanshu Madhani <hmadhani@marvell.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
drivers/scsi/qla2xxx/qla_os.c

index 6d5dfe12760e23fe00fe0745e59f54da1db18eb3..4fc1474c5a261038d6322f60542e55174659a422 100644 (file)
@@ -764,25 +764,8 @@ qla2xxx_qpair_sp_free_dma(void *ptr)
                sp->flags &= ~SRB_CRC_CTX_DSD_VALID;
        }
 
-       if (sp->flags & SRB_CRC_CTX_DMA_VALID) {
-               struct crc_context *ctx0 = ctx;
-
-               dma_pool_free(ha->dl_dma_pool, ctx, ctx0->crc_ctx_dma);
-               sp->flags &= ~SRB_CRC_CTX_DMA_VALID;
-       }
-
-       if (sp->flags & SRB_FCP_CMND_DMA_VALID) {
-               struct ct6_dsd *ctx1 = ctx;
-               dma_pool_free(ha->fcp_cmnd_dma_pool, ctx1->fcp_cmnd,
-                   ctx1->fcp_cmnd_dma);
-               list_splice(&ctx1->dsd_list, &ha->gbl_dsd_list);
-               ha->gbl_dsd_inuse -= ctx1->dsd_use_cnt;
-               ha->gbl_dsd_avail += ctx1->dsd_use_cnt;
-               mempool_free(ctx1, ha->ctx_mempool);
-               sp->flags &= ~SRB_FCP_CMND_DMA_VALID;
-       }
        if (sp->flags & SRB_DIF_BUNDL_DMA_VALID) {
-               struct crc_context *difctx = sp->u.scmd.ctx;
+               struct crc_context *difctx = ctx;
                struct dsd_dma *dif_dsd, *nxt_dsd;
 
                list_for_each_entry_safe(dif_dsd, nxt_dsd,
@@ -816,6 +799,25 @@ qla2xxx_qpair_sp_free_dma(void *ptr)
                }
                sp->flags &= ~SRB_DIF_BUNDL_DMA_VALID;
        }
+
+       if (sp->flags & SRB_FCP_CMND_DMA_VALID) {
+               struct ct6_dsd *ctx1 = ctx;
+
+               dma_pool_free(ha->fcp_cmnd_dma_pool, ctx1->fcp_cmnd,
+                   ctx1->fcp_cmnd_dma);
+               list_splice(&ctx1->dsd_list, &ha->gbl_dsd_list);
+               ha->gbl_dsd_inuse -= ctx1->dsd_use_cnt;
+               ha->gbl_dsd_avail += ctx1->dsd_use_cnt;
+               mempool_free(ctx1, ha->ctx_mempool);
+               sp->flags &= ~SRB_FCP_CMND_DMA_VALID;
+       }
+
+       if (sp->flags & SRB_CRC_CTX_DMA_VALID) {
+               struct crc_context *ctx0 = ctx;
+
+               dma_pool_free(ha->dl_dma_pool, ctx, ctx0->crc_ctx_dma);
+               sp->flags &= ~SRB_CRC_CTX_DMA_VALID;
+       }
 }
 
 void