diff options
author | Bart Van Assche | 2019-04-17 14:44:25 -0700 |
---|---|---|
committer | Martin K. Petersen | 2019-04-29 17:24:50 -0400 |
commit | d8f945bf8096375f458683b5718722a2d5dda2f0 (patch) | |
tree | 16e4abb84efc04039aec9d9ce7781b067c013a30 /drivers/scsi | |
parent | 24afabdbd0b3553963a2bbf465895492b14d1107 (diff) |
scsi: qla2xxx: Fix use-after-free issues in qla2xxx_qpair_sp_free_dma()
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>
Diffstat (limited to 'drivers/scsi')
-rw-r--r-- | drivers/scsi/qla2xxx/qla_os.c | 38 |
1 files changed, 20 insertions, 18 deletions
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c index 6d5dfe12760e..4fc1474c5a26 100644 --- a/drivers/scsi/qla2xxx/qla_os.c +++ b/drivers/scsi/qla2xxx/qla_os.c @@ -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 |