In GID_PT mode with lpfc_ns_query=1, a race condition between iterating the vport->fc_nodes list in lpfc_rscn_recovery_check and cleanup of an ndlp can trigger a crash while processing the RSCN of another initiator from the same zone. During iteration of the vport->fc_nodes list, an ndlp is cleaned up and released. lpfc_dequeue_node is called from lpfc_cleanup_node leading to a bad ndlp dereference in lpfc_rscn_recovery_check. Change list_for_each_entry to list_for_each_entry_safe in lpfc_rscn_recovery_check to protect against removal of an initiator ndlp, while walking the vport->fc_nodes list. Co-developed-by: Justin Tee <justin.tee@xxxxxxxxxxxx> Signed-off-by: Justin Tee <justin.tee@xxxxxxxxxxxx> Signed-off-by: James Smart <jsmart2021@xxxxxxxxx> --- drivers/scsi/lpfc/lpfc_els.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index 583a287b2d0c..3671e0f8e041 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c @@ -7708,10 +7708,10 @@ lpfc_rscn_payload_check(struct lpfc_vport *vport, uint32_t did) static int lpfc_rscn_recovery_check(struct lpfc_vport *vport) { - struct lpfc_nodelist *ndlp = NULL; + struct lpfc_nodelist *ndlp = NULL, *n; /* Move all affected nodes by pending RSCNs to NPR state. */ - list_for_each_entry(ndlp, &vport->fc_nodes, nlp_listp) { + list_for_each_entry_safe(ndlp, n, &vport->fc_nodes, nlp_listp) { if ((ndlp->nlp_state == NLP_STE_UNUSED_NODE) || !lpfc_rscn_payload_check(vport, ndlp->nlp_DID)) continue; -- 2.26.2