Commit e3715fa3 authored by Justin Tee's avatar Justin Tee Committed by Yongqiang Liu
Browse files

scsi: lpfc: Validate hdwq pointers before dereferencing in reset/errata paths

mainline inclusion
from mainline-v6.12-rc1
commit 2be1d4f11944cd6283cb97268b3e17c4424945ca
category: bugfix
bugzilla: https://gitee.com/src-openeuler/kernel/issues/IAYR9Z
CVE: CVE-2024-49891

Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=2be1d4f11944cd6283cb97268b3e17c4424945ca



--------------------------------

When the HBA is undergoing a reset or is handling an errata event, NULL ptr
dereference crashes may occur in routines such as
lpfc_sli_flush_io_rings(), lpfc_dev_loss_tmo_callbk(), or
lpfc_abort_handler().

Add NULL ptr checks before dereferencing hdwq pointers that may have been
freed due to operations colliding with a reset or errata event handler.

Signed-off-by: default avatarJustin Tee <justin.tee@broadcom.com>
Link: https://lore.kernel.org/r/20240726231512.92867-4-justintee8345@gmail.com


Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
Conflicts:
	drivers/scsi/lpfc/lpfc_hbadisc.c
	drivers/scsi/lpfc/lpfc_scsi.c
	drivers/scsi/lpfc/lpfc_sli.c
[Yongqiang: fix conflicts with no test_bit and build warning]
Signed-off-by: default avatarYongqiang Liu <liuyongqiang13@huawei.com>
parent e64d5ad2
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -175,7 +175,8 @@ lpfc_dev_loss_tmo_callbk(struct fc_rport *rport)
			 ndlp->nlp_state, ndlp->fc4_xpt_flags);

	/* Don't schedule a worker thread event if the vport is going down. */
	if (vport->load_flag & FC_UNLOADING) {
	if (vport->load_flag & FC_UNLOADING ||
	    !(phba->hba_flag & HBA_SETUP)) {
		spin_lock_irqsave(&ndlp->lock, iflags);
		ndlp->rport = NULL;

+11 −2
Original line number Diff line number Diff line
@@ -5546,11 +5546,20 @@ lpfc_abort_handler(struct scsi_cmnd *cmnd)

	iocb = &lpfc_cmd->cur_iocbq;
	if (phba->sli_rev == LPFC_SLI_REV4) {
		pring_s4 = phba->sli4_hba.hdwq[iocb->hba_wqidx].io_wq->pring;
		if (!pring_s4) {
		/* if the io_wq & pring are gone, the port was reset. */
		if (!phba->sli4_hba.hdwq[iocb->hba_wqidx].io_wq ||
		    !phba->sli4_hba.hdwq[iocb->hba_wqidx].io_wq->pring) {
			lpfc_printf_vlog(vport, KERN_WARNING, LOG_FCP,
					 "2877 SCSI Layer I/O Abort Request "
					 "IO CMPL Status x%x ID %d LUN %llu "
					 "HBA_SETUP %d\n", FAILED,
					 cmnd->device->id,
					 (u64)cmnd->device->lun,
					 phba->hba_flag & HBA_SETUP);
			ret = FAILED;
			goto out_unlock_hba;
		}
		pring_s4 = phba->sli4_hba.hdwq[iocb->hba_wqidx].io_wq->pring;
		spin_lock(&pring_s4->ring_lock);
	}
	/* the command is in process of being cancelled */
+11 −0
Original line number Diff line number Diff line
@@ -4684,6 +4684,17 @@ lpfc_sli_flush_io_rings(struct lpfc_hba *phba)
	/* Look on all the FCP Rings for the iotag */
	if (phba->sli_rev >= LPFC_SLI_REV4) {
		for (i = 0; i < phba->cfg_hdw_queue; i++) {
			if (!phba->sli4_hba.hdwq ||
			    !phba->sli4_hba.hdwq[i].io_wq) {
				lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
						"7777 hdwq's deleted %x "
						"%x %x %x\n",
						phba->pport->load_flag,
						phba->hba_flag,
						phba->link_state,
						phba->sli.sli_flag);
				return;
			}
			pring = phba->sli4_hba.hdwq[i].io_wq->pring;
			spin_lock_irq(&pring->ring_lock);