| From: Quinn Tran <quinn.tran@cavium.com> |
| Date: Fri, 23 Dec 2016 18:06:10 -0800 |
| Subject: qla2xxx: Fix crash due to null pointer access |
| |
| commit fc1ffd6cb38a1c1af625b9833c41928039e733f5 upstream. |
| |
| During code inspection, while investigating following stack trace |
| seen on one of the test setup, we found out there was possibility |
| of memory leak becuase driver was not unwinding the stack properly. |
| |
| This issue has not been reproduced in a test environment or on a |
| customer setup. |
| |
| Here's stack trace that was seen. |
| |
| [1469877.797315] Call Trace: |
| [1469877.799940] [<ffffffffa03ab6e9>] qla2x00_mem_alloc+0xb09/0x10c0 [qla2xxx] |
| [1469877.806980] [<ffffffffa03ac50a>] qla2x00_probe_one+0x86a/0x1b50 [qla2xxx] |
| [1469877.814013] [<ffffffff813b6d01>] ? __pm_runtime_resume+0x51/0xa0 |
| [1469877.820265] [<ffffffff8157c1f5>] ? _raw_spin_lock_irqsave+0x25/0x90 |
| [1469877.826776] [<ffffffff8157cd2d>] ? _raw_spin_unlock_irqrestore+0x6d/0x80 |
| [1469877.833720] [<ffffffff810741d1>] ? preempt_count_sub+0xb1/0x100 |
| [1469877.839885] [<ffffffff8157cd0c>] ? _raw_spin_unlock_irqrestore+0x4c/0x80 |
| [1469877.846830] [<ffffffff81319b9c>] local_pci_probe+0x4c/0xb0 |
| [1469877.852562] [<ffffffff810741d1>] ? preempt_count_sub+0xb1/0x100 |
| [1469877.858727] [<ffffffff81319c89>] pci_call_probe+0x89/0xb0 |
| |
| Signed-off-by: Quinn Tran <quinn.tran@cavium.com> |
| Signed-off-by: Himanshu Madhani <himanshu.madhani@cavium.com> |
| Reviewed-by: Christoph Hellwig <hch@lst.de> |
| [ bvanassche: Fixed spelling in patch description ] |
| Signed-off-by: Bart Van Assche <bart.vanassche@sandisk.com> |
| Signed-off-by: Ben Hutchings <ben@decadent.org.uk> |
| --- |
| drivers/scsi/qla2xxx/qla_os.c | 16 ++++++++++++---- |
| 1 file changed, 12 insertions(+), 4 deletions(-) |
| |
| --- a/drivers/scsi/qla2xxx/qla_os.c |
| +++ b/drivers/scsi/qla2xxx/qla_os.c |
| @@ -3393,7 +3393,7 @@ qla2x00_mem_alloc(struct qla_hw_data *ha |
| sizeof(struct ct6_dsd), 0, |
| SLAB_HWCACHE_ALIGN, NULL); |
| if (!ctx_cachep) |
| - goto fail_free_gid_list; |
| + goto fail_free_srb_mempool; |
| } |
| ha->ctx_mempool = mempool_create_slab_pool(SRB_MIN_REQ, |
| ctx_cachep); |
| @@ -3546,7 +3546,7 @@ qla2x00_mem_alloc(struct qla_hw_data *ha |
| ha->loop_id_map = kzalloc(BITS_TO_LONGS(LOOPID_MAP_SIZE) * sizeof(long), |
| GFP_KERNEL); |
| if (!ha->loop_id_map) |
| - goto fail_async_pd; |
| + goto fail_loop_id_map; |
| else { |
| qla2x00_set_reserved_loop_ids(ha); |
| ql_dbg_pci(ql_dbg_init, ha->pdev, 0x0123, |
| @@ -3555,6 +3555,8 @@ qla2x00_mem_alloc(struct qla_hw_data *ha |
| |
| return 0; |
| |
| +fail_loop_id_map: |
| + dma_pool_free(ha->s_dma_pool, ha->async_pd, ha->async_pd_dma); |
| fail_async_pd: |
| dma_pool_free(ha->s_dma_pool, ha->ex_init_cb, ha->ex_init_cb_dma); |
| fail_ex_init_cb: |
| @@ -3582,6 +3584,10 @@ fail_free_ms_iocb: |
| dma_pool_free(ha->s_dma_pool, ha->ms_iocb, ha->ms_iocb_dma); |
| ha->ms_iocb = NULL; |
| ha->ms_iocb_dma = 0; |
| + |
| + if (ha->sns_cmd) |
| + dma_free_coherent(&ha->pdev->dev, sizeof(struct sns_cmd_pkt), |
| + ha->sns_cmd, ha->sns_cmd_dma); |
| fail_dma_pool: |
| if (IS_QLA82XX(ha) || ql2xenabledif) { |
| dma_pool_destroy(ha->fcp_cmnd_dma_pool); |
| @@ -3599,10 +3605,12 @@ fail_free_nvram: |
| kfree(ha->nvram); |
| ha->nvram = NULL; |
| fail_free_ctx_mempool: |
| - mempool_destroy(ha->ctx_mempool); |
| + if (ha->ctx_mempool) |
| + mempool_destroy(ha->ctx_mempool); |
| ha->ctx_mempool = NULL; |
| fail_free_srb_mempool: |
| - mempool_destroy(ha->srb_mempool); |
| + if (ha->srb_mempool) |
| + mempool_destroy(ha->srb_mempool); |
| ha->srb_mempool = NULL; |
| fail_free_gid_list: |
| dma_free_coherent(&ha->pdev->dev, qla2x00_gid_list_size(ha), |