Commit d7baf9e3 authored by Justin Tee's avatar Justin Tee Committed by Ye Bin
Browse files

scsi: lpfc: Release hbalock before calling lpfc_worker_wake_up()

mainline inclusion
from mainline-v6.9-rc2
commit ded20192dff31c91cef2a04f7e20e60e9bb887d3
category: bugfix
bugzilla: https://gitee.com/src-openeuler/kernel/issues/I9U211
CVE: CVE-2024-36924

Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=ded20192dff31c91cef2a04f7e20e60e9bb887d3



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

lpfc_worker_wake_up() calls the lpfc_work_done() routine, which takes the
hbalock.  Thus, lpfc_worker_wake_up() should not be called while holding the
hbalock to avoid potential deadlock.

Signed-off-by: default avatarJustin Tee <justin.tee@broadcom.com>
Link: https://lore.kernel.org/r/20240305200503.57317-7-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_sli.c
[fix context diff]
Signed-off-by: default avatarYe Bin <yebin@huaweicloud.com>
parent d2901c3f
Loading
Loading
Loading
Loading
+10 −10
Original line number Diff line number Diff line
@@ -3173,23 +3173,23 @@ lpfc_els_retry_delay(struct timer_list *t)
	unsigned long flags;
	struct lpfc_work_evt  *evtp = &ndlp->els_retry_evt;

	/* Hold a node reference for outstanding queued work */
	if (!lpfc_nlp_get(ndlp))
		return;

	spin_lock_irqsave(&phba->hbalock, flags);
	if (!list_empty(&evtp->evt_listp)) {
		spin_unlock_irqrestore(&phba->hbalock, flags);
		lpfc_nlp_put(ndlp);
		return;
	}

	/* We need to hold the node by incrementing the reference
	 * count until the queued work is done
	 */
	evtp->evt_arg1  = lpfc_nlp_get(ndlp);
	if (evtp->evt_arg1) {
	evtp->evt_arg1 = ndlp;
	evtp->evt = LPFC_EVT_ELS_RETRY;
	list_add_tail(&evtp->evt_listp, &phba->work_list);
		lpfc_worker_wake_up(phba);
	}
	spin_unlock_irqrestore(&phba->hbalock, flags);
	return;

	lpfc_worker_wake_up(phba);
}

/**
+2 −0
Original line number Diff line number Diff line
@@ -183,7 +183,9 @@ lpfc_dev_loss_tmo_callbk(struct fc_rport *rport)
	if (evtp->evt_arg1) {
		evtp->evt = LPFC_EVT_DEV_LOSS;
		list_add_tail(&evtp->evt_listp, &phba->work_list);
		spin_unlock_irq(&phba->hbalock);
		lpfc_worker_wake_up(phba);
		return;
	}
	spin_unlock_irq(&phba->hbalock);

+1 −1
Original line number Diff line number Diff line
@@ -1104,9 +1104,9 @@ lpfc_set_rrq_active(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp,
	empty = list_empty(&phba->active_rrq_list);
	list_add_tail(&rrq->list, &phba->active_rrq_list);
	phba->hba_flag |= HBA_RRQ_ACTIVE;
	spin_unlock_irqrestore(&phba->hbalock, iflags);
	if (empty)
		lpfc_worker_wake_up(phba);
	spin_unlock_irqrestore(&phba->hbalock, iflags);
	return 0;
out:
	spin_unlock_irqrestore(&phba->hbalock, iflags);