Skip to content

Commit 6a2cf8d

Browse files
bkstratusmartinkpetersen
authored andcommitted
scsi: qla2xxx: Fix crashes in qla2x00_probe_one on probe failure
Because of the shifting around of code in qla2x00_probe_one recently, failures during adapter initialization can lead to problems, i.e. NULL pointer crashes and doubly freed data structures which cause eventual panics. This V2 version makes the relevant memory free routines idempotent, so repeat calls won't cause any harm. I also removed the problematic probe_init_failed exit point as it is not needed. Fixes: d64d6c5 ("scsi: qla2xxx: Fix NULL pointer crash due to probe failure") Signed-off-by: Bill Kuzeja <[email protected]> Acked-by: Himanshu Madhani <[email protected]> Reviewed-by: Hannes Reinecke <[email protected]> Signed-off-by: Martin K. Petersen <[email protected]>
1 parent 4b43392 commit 6a2cf8d

File tree

1 file changed

+37
-22
lines changed

1 file changed

+37
-22
lines changed

drivers/scsi/qla2xxx/qla_os.c

Lines changed: 37 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -454,7 +454,7 @@ static int qla2x00_alloc_queues(struct qla_hw_data *ha, struct req_que *req,
454454
ha->req_q_map[0] = req;
455455
set_bit(0, ha->rsp_qid_map);
456456
set_bit(0, ha->req_qid_map);
457-
return 1;
457+
return 0;
458458

459459
fail_qpair_map:
460460
kfree(ha->base_qpair);
@@ -471,6 +471,9 @@ static int qla2x00_alloc_queues(struct qla_hw_data *ha, struct req_que *req,
471471

472472
static void qla2x00_free_req_que(struct qla_hw_data *ha, struct req_que *req)
473473
{
474+
if (!ha->req_q_map)
475+
return;
476+
474477
if (IS_QLAFX00(ha)) {
475478
if (req && req->ring_fx00)
476479
dma_free_coherent(&ha->pdev->dev,
@@ -481,14 +484,17 @@ static void qla2x00_free_req_que(struct qla_hw_data *ha, struct req_que *req)
481484
(req->length + 1) * sizeof(request_t),
482485
req->ring, req->dma);
483486

484-
if (req)
487+
if (req) {
485488
kfree(req->outstanding_cmds);
486-
487-
kfree(req);
489+
kfree(req);
490+
}
488491
}
489492

490493
static void qla2x00_free_rsp_que(struct qla_hw_data *ha, struct rsp_que *rsp)
491494
{
495+
if (!ha->rsp_q_map)
496+
return;
497+
492498
if (IS_QLAFX00(ha)) {
493499
if (rsp && rsp->ring)
494500
dma_free_coherent(&ha->pdev->dev,
@@ -499,7 +505,8 @@ static void qla2x00_free_rsp_que(struct qla_hw_data *ha, struct rsp_que *rsp)
499505
(rsp->length + 1) * sizeof(response_t),
500506
rsp->ring, rsp->dma);
501507
}
502-
kfree(rsp);
508+
if (rsp)
509+
kfree(rsp);
503510
}
504511

505512
static void qla2x00_free_queues(struct qla_hw_data *ha)
@@ -1723,6 +1730,8 @@ __qla2x00_abort_all_cmds(struct qla_qpair *qp, int res)
17231730
struct qla_tgt_cmd *cmd;
17241731
uint8_t trace = 0;
17251732

1733+
if (!ha->req_q_map)
1734+
return;
17261735
spin_lock_irqsave(qp->qp_lock_ptr, flags);
17271736
req = qp->req;
17281737
for (cnt = 1; cnt < req->num_outstanding_cmds; cnt++) {
@@ -3095,14 +3104,14 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
30953104
/* Set up the irqs */
30963105
ret = qla2x00_request_irqs(ha, rsp);
30973106
if (ret)
3098-
goto probe_hw_failed;
3107+
goto probe_failed;
30993108

31003109
/* Alloc arrays of request and response ring ptrs */
3101-
if (!qla2x00_alloc_queues(ha, req, rsp)) {
3110+
if (qla2x00_alloc_queues(ha, req, rsp)) {
31023111
ql_log(ql_log_fatal, base_vha, 0x003d,
31033112
"Failed to allocate memory for queue pointers..."
31043113
"aborting.\n");
3105-
goto probe_init_failed;
3114+
goto probe_failed;
31063115
}
31073116

31083117
if (ha->mqenable && shost_use_blk_mq(host)) {
@@ -3387,15 +3396,6 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
33873396

33883397
return 0;
33893398

3390-
probe_init_failed:
3391-
qla2x00_free_req_que(ha, req);
3392-
ha->req_q_map[0] = NULL;
3393-
clear_bit(0, ha->req_qid_map);
3394-
qla2x00_free_rsp_que(ha, rsp);
3395-
ha->rsp_q_map[0] = NULL;
3396-
clear_bit(0, ha->rsp_qid_map);
3397-
ha->max_req_queues = ha->max_rsp_queues = 0;
3398-
33993399
probe_failed:
34003400
if (base_vha->timer_active)
34013401
qla2x00_stop_timer(base_vha);
@@ -4508,11 +4508,17 @@ qla2x00_mem_free(struct qla_hw_data *ha)
45084508
if (ha->init_cb)
45094509
dma_free_coherent(&ha->pdev->dev, ha->init_cb_size,
45104510
ha->init_cb, ha->init_cb_dma);
4511-
vfree(ha->optrom_buffer);
4512-
kfree(ha->nvram);
4513-
kfree(ha->npiv_info);
4514-
kfree(ha->swl);
4515-
kfree(ha->loop_id_map);
4511+
4512+
if (ha->optrom_buffer)
4513+
vfree(ha->optrom_buffer);
4514+
if (ha->nvram)
4515+
kfree(ha->nvram);
4516+
if (ha->npiv_info)
4517+
kfree(ha->npiv_info);
4518+
if (ha->swl)
4519+
kfree(ha->swl);
4520+
if (ha->loop_id_map)
4521+
kfree(ha->loop_id_map);
45164522

45174523
ha->srb_mempool = NULL;
45184524
ha->ctx_mempool = NULL;
@@ -4528,6 +4534,15 @@ qla2x00_mem_free(struct qla_hw_data *ha)
45284534
ha->ex_init_cb_dma = 0;
45294535
ha->async_pd = NULL;
45304536
ha->async_pd_dma = 0;
4537+
ha->loop_id_map = NULL;
4538+
ha->npiv_info = NULL;
4539+
ha->optrom_buffer = NULL;
4540+
ha->swl = NULL;
4541+
ha->nvram = NULL;
4542+
ha->mctp_dump = NULL;
4543+
ha->dcbx_tlv = NULL;
4544+
ha->xgmac_data = NULL;
4545+
ha->sfp_data = NULL;
45314546

45324547
ha->s_dma_pool = NULL;
45334548
ha->dl_dma_pool = NULL;

0 commit comments

Comments
 (0)