Commit 5e53be8e authored by Quinn Tran's avatar Quinn Tran Committed by Martin K. Petersen
Browse files

scsi: qla2xxx: Fix memory leak for allocating abort IOCB



In the case of IOCB QFull, Initiator code can leave behind a stale pointer
to an SRB structure on the outstanding command array.

Fixes: 82de802a ("scsi: qla2xxx: Preparation for Target MQ.")
Cc: stable@vger.kernel.org #v4.16+
Signed-off-by: default avatarQuinn Tran <quinn.tran@cavium.com>
Signed-off-by: default avatarHimanshu Madhani <himanshu.madhani@cavium.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent b4146c49
Loading
Loading
Loading
Loading
+27 −26
Original line number Diff line number Diff line
@@ -2130,34 +2130,11 @@ __qla2x00_alloc_iocbs(struct qla_qpair *qpair, srb_t *sp)
	req_cnt = 1;
	handle = 0;

	if (!sp)
		goto skip_cmd_array;

	/* Check for room in outstanding command list. */
	handle = req->current_outstanding_cmd;
	for (index = 1; index < req->num_outstanding_cmds; index++) {
		handle++;
		if (handle == req->num_outstanding_cmds)
			handle = 1;
		if (!req->outstanding_cmds[handle])
			break;
	}
	if (index == req->num_outstanding_cmds) {
		ql_log(ql_log_warn, vha, 0x700b,
		    "No room on outstanding cmd array.\n");
		goto queuing_error;
	}

	/* Prep command array. */
	req->current_outstanding_cmd = handle;
	req->outstanding_cmds[handle] = sp;
	sp->handle = handle;

	if (sp && (sp->type != SRB_SCSI_CMD)) {
		/* Adjust entry-counts as needed. */
	if (sp->type != SRB_SCSI_CMD)
		req_cnt = sp->iocbs;
	}

skip_cmd_array:
	/* Check for room on request queue. */
	if (req->cnt < req_cnt + 2) {
		if (qpair->use_shadow_reg)
@@ -2183,6 +2160,28 @@ skip_cmd_array:
	if (req->cnt < req_cnt + 2)
		goto queuing_error;

	if (sp) {
		/* Check for room in outstanding command list. */
		handle = req->current_outstanding_cmd;
		for (index = 1; index < req->num_outstanding_cmds; index++) {
			handle++;
			if (handle == req->num_outstanding_cmds)
				handle = 1;
			if (!req->outstanding_cmds[handle])
				break;
		}
		if (index == req->num_outstanding_cmds) {
			ql_log(ql_log_warn, vha, 0x700b,
			    "No room on outstanding cmd array.\n");
			goto queuing_error;
		}

		/* Prep command array. */
		req->current_outstanding_cmd = handle;
		req->outstanding_cmds[handle] = sp;
		sp->handle = handle;
	}

	/* Prep packet */
	req->cnt -= req_cnt;
	pkt = req->ring_ptr;
@@ -2195,6 +2194,8 @@ skip_cmd_array:
		pkt->handle = handle;
	}

	return pkt;

queuing_error:
	qpair->tgt_counters.num_alloc_iocb_failed++;
	return pkt;