]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
5.15-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 23 Apr 2025 13:46:00 +0000 (15:46 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 23 Apr 2025 13:46:00 +0000 (15:46 +0200)
added patches:
scsi-lpfc-fix-null-pointer-dereference-after-failing-to-issue-flogi-and-plogi.patch

queue-5.15/scsi-lpfc-fix-null-pointer-dereference-after-failing-to-issue-flogi-and-plogi.patch [new file with mode: 0644]
queue-5.15/series

diff --git a/queue-5.15/scsi-lpfc-fix-null-pointer-dereference-after-failing-to-issue-flogi-and-plogi.patch b/queue-5.15/scsi-lpfc-fix-null-pointer-dereference-after-failing-to-issue-flogi-and-plogi.patch
new file mode 100644 (file)
index 0000000..5b9100b
--- /dev/null
@@ -0,0 +1,167 @@
+From 577a942df3de2666f6947bdd3a5c9e8d30073424 Mon Sep 17 00:00:00 2001
+From: James Smart <jsmart2021@gmail.com>
+Date: Tue, 12 Apr 2022 15:19:50 -0700
+Subject: scsi: lpfc: Fix null pointer dereference after failing to issue FLOGI and PLOGI
+
+From: James Smart <jsmart2021@gmail.com>
+
+commit 577a942df3de2666f6947bdd3a5c9e8d30073424 upstream.
+
+If lpfc_issue_els_flogi() fails and returns non-zero status, the node
+reference count is decremented to trigger the release of the nodelist
+structure. However, if there is a prior registration or dev-loss-evt work
+pending, the node may be released prematurely.  When dev-loss-evt
+completes, the released node is referenced causing a use-after-free null
+pointer dereference.
+
+Similarly, when processing non-zero ELS PLOGI completion status in
+lpfc_cmpl_els_plogi(), the ndlp flags are checked for a transport
+registration before triggering node removal.  If dev-loss-evt work is
+pending, the node may be released prematurely and a subsequent call to
+lpfc_dev_loss_tmo_handler() results in a use after free ndlp dereference.
+
+Add test for pending dev-loss before decrementing the node reference count
+for FLOGI, PLOGI, PRLI, and ADISC handling.
+
+Link: https://lore.kernel.org/r/20220412222008.126521-9-jsmart2021@gmail.com
+Co-developed-by: Justin Tee <justin.tee@broadcom.com>
+Signed-off-by: Justin Tee <justin.tee@broadcom.com>
+Signed-off-by: James Smart <jsmart2021@gmail.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+[Minor context change fixed.]
+Signed-off-by: Bin Lan <bin.lan.cn@windriver.com>
+Signed-off-by: He Zhe <zhe.he@windriver.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/scsi/lpfc/lpfc_els.c |   51 +++++++++++++++++++++++++++++--------------
+ 1 file changed, 35 insertions(+), 16 deletions(-)
+
+--- a/drivers/scsi/lpfc/lpfc_els.c
++++ b/drivers/scsi/lpfc/lpfc_els.c
+@@ -1517,10 +1517,13 @@ lpfc_initial_flogi(struct lpfc_vport *vp
+       }
+       if (lpfc_issue_els_flogi(vport, ndlp, 0)) {
+-              /* This decrement of reference count to node shall kick off
+-               * the release of the node.
++              /* A node reference should be retained while registered with a
++               * transport or dev-loss-evt work is pending.
++               * Otherwise, decrement node reference to trigger release.
+                */
+-              lpfc_nlp_put(ndlp);
++              if (!(ndlp->fc4_xpt_flags & (SCSI_XPT_REGD | NVME_XPT_REGD)) &&
++                  !(ndlp->nlp_flag & NLP_IN_DEV_LOSS))
++                      lpfc_nlp_put(ndlp);
+               return 0;
+       }
+       return 1;
+@@ -1563,10 +1566,13 @@ lpfc_initial_fdisc(struct lpfc_vport *vp
+       }
+       if (lpfc_issue_els_fdisc(vport, ndlp, 0)) {
+-              /* decrement node reference count to trigger the release of
+-               * the node.
++              /* A node reference should be retained while registered with a
++               * transport or dev-loss-evt work is pending.
++               * Otherwise, decrement node reference to trigger release.
+                */
+-              lpfc_nlp_put(ndlp);
++              if (!(ndlp->fc4_xpt_flags & (SCSI_XPT_REGD | NVME_XPT_REGD)) &&
++                  !(ndlp->nlp_flag & NLP_IN_DEV_LOSS))
++                      lpfc_nlp_put(ndlp);
+               return 0;
+       }
+       return 1;
+@@ -1967,6 +1973,7 @@ lpfc_cmpl_els_plogi(struct lpfc_hba *phb
+       struct lpfc_dmabuf *prsp;
+       int disc;
+       struct serv_parm *sp = NULL;
++      bool release_node = false;
+       /* we pass cmdiocb to state machine which needs rspiocb as well */
+       cmdiocb->context_un.rsp_iocb = rspiocb;
+@@ -2047,19 +2054,21 @@ lpfc_cmpl_els_plogi(struct lpfc_hba *phb
+                       spin_unlock_irq(&ndlp->lock);
+                       goto out;
+               }
+-              spin_unlock_irq(&ndlp->lock);
+               /* No PLOGI collision and the node is not registered with the
+                * scsi or nvme transport. It is no longer an active node. Just
+                * start the device remove process.
+                */
+               if (!(ndlp->fc4_xpt_flags & (SCSI_XPT_REGD | NVME_XPT_REGD))) {
+-                      spin_lock_irq(&ndlp->lock);
+                       ndlp->nlp_flag &= ~NLP_NPR_2B_DISC;
+-                      spin_unlock_irq(&ndlp->lock);
++                      if (!(ndlp->nlp_flag & NLP_IN_DEV_LOSS))
++                              release_node = true;
++              }
++              spin_unlock_irq(&ndlp->lock);
++
++              if (release_node)
+                       lpfc_disc_state_machine(vport, ndlp, cmdiocb,
+                                               NLP_EVT_DEVICE_RM);
+-              }
+       } else {
+               /* Good status, call state machine */
+               prsp = list_entry(((struct lpfc_dmabuf *)
+@@ -2269,6 +2278,7 @@ lpfc_cmpl_els_prli(struct lpfc_hba *phba
+       struct lpfc_nodelist *ndlp;
+       char *mode;
+       u32 loglevel;
++      bool release_node = false;
+       /* we pass cmdiocb to state machine which needs rspiocb as well */
+       cmdiocb->context_un.rsp_iocb = rspiocb;
+@@ -2335,14 +2345,18 @@ lpfc_cmpl_els_prli(struct lpfc_hba *phba
+                * it is no longer an active node.  Otherwise devloss
+                * handles the final cleanup.
+                */
++              spin_lock_irq(&ndlp->lock);
+               if (!(ndlp->fc4_xpt_flags & (SCSI_XPT_REGD | NVME_XPT_REGD)) &&
+                   !ndlp->fc4_prli_sent) {
+-                      spin_lock_irq(&ndlp->lock);
+                       ndlp->nlp_flag &= ~NLP_NPR_2B_DISC;
+-                      spin_unlock_irq(&ndlp->lock);
++                      if (!(ndlp->nlp_flag & NLP_IN_DEV_LOSS))
++                              release_node = true;
++              }
++              spin_unlock_irq(&ndlp->lock);
++
++              if (release_node)
+                       lpfc_disc_state_machine(vport, ndlp, cmdiocb,
+                                               NLP_EVT_DEVICE_RM);
+-              }
+       } else {
+               /* Good status, call state machine.  However, if another
+                * PRLI is outstanding, don't call the state machine
+@@ -2713,6 +2727,7 @@ lpfc_cmpl_els_adisc(struct lpfc_hba *phb
+       IOCB_t *irsp;
+       struct lpfc_nodelist *ndlp;
+       int  disc;
++      bool release_node = false;
+       /* we pass cmdiocb to state machine which needs rspiocb as well */
+       cmdiocb->context_un.rsp_iocb = rspiocb;
+@@ -2771,13 +2786,17 @@ lpfc_cmpl_els_adisc(struct lpfc_hba *phb
+                * transport, it is no longer an active node. Otherwise
+                * devloss handles the final cleanup.
+                */
++              spin_lock_irq(&ndlp->lock);
+               if (!(ndlp->fc4_xpt_flags & (SCSI_XPT_REGD | NVME_XPT_REGD))) {
+-                      spin_lock_irq(&ndlp->lock);
+                       ndlp->nlp_flag &= ~NLP_NPR_2B_DISC;
+-                      spin_unlock_irq(&ndlp->lock);
++                      if (!(ndlp->nlp_flag & NLP_IN_DEV_LOSS))
++                              release_node = true;
++              }
++              spin_unlock_irq(&ndlp->lock);
++
++              if (release_node)
+                       lpfc_disc_state_machine(vport, ndlp, cmdiocb,
+                                               NLP_EVT_DEVICE_RM);
+-              }
+       } else
+               /* Good status, call state machine */
+               lpfc_disc_state_machine(vport, ndlp, cmdiocb,
index 5abcc1a786d860329a269a42686e4f3629cce23d..a5029b5207c98b129993682dab33b2c74829fc84 100644 (file)
@@ -250,3 +250,4 @@ mm-fix-apply_to_existing_page_range.patch
 f2fs-check-validation-of-fault-attrs-in-f2fs_build_fault_attr.patch
 pmdomain-ti-add-a-null-pointer-check-to-the-omap_prm_domain_init.patch
 net-sched-act_mirred-don-t-override-retval-if-we-already-lost-the-skb.patch
+scsi-lpfc-fix-null-pointer-dereference-after-failing-to-issue-flogi-and-plogi.patch