diff options
author | Justin Tee <justin.tee@broadcom.com> | 2023-10-09 09:18:10 -0700 |
---|---|---|
committer | Martin K. Petersen <martin.petersen@oracle.com> | 2023-10-13 16:58:27 -0400 |
commit | a3c3c0a806f1bb7d89f139d8225092faad0cf04a (patch) | |
tree | 8402aaf87401934814719f9c147e450caa6394b3 /drivers/scsi | |
parent | 12e896c74280d9d8da87327f08cf0e878d24ae5c (diff) |
scsi: lpfc: Validate ELS LS_ACC completion payload
A WCQE success completion status does not guarantee valid LS_ACC receipt
for ELS commands. So, introduce a small helper routine that validates ELS
LS_ACC frames in ELS cmpl routines.
Signed-off-by: Justin Tee <justin.tee@broadcom.com>
Link: https://lore.kernel.org/r/20231009161812.97232-5-justintee8345@gmail.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Diffstat (limited to 'drivers/scsi')
-rw-r--r-- | drivers/scsi/lpfc/lpfc_els.c | 23 |
1 files changed, 23 insertions, 0 deletions
diff --git a/drivers/scsi/lpfc/lpfc_els.c b/drivers/scsi/lpfc/lpfc_els.c index 54e47f268235..f9627eddab08 100644 --- a/drivers/scsi/lpfc/lpfc_els.c +++ b/drivers/scsi/lpfc/lpfc_els.c @@ -131,6 +131,15 @@ lpfc_els_chk_latt(struct lpfc_vport *vport) return 1; } +static bool lpfc_is_els_acc_rsp(struct lpfc_dmabuf *buf) +{ + struct fc_els_ls_acc *rsp = buf->virt; + + if (rsp && rsp->la_cmd == ELS_LS_ACC) + return true; + return false; +} + /** * lpfc_prep_els_iocb - Allocate and prepare a lpfc iocb data structure * @vport: pointer to a host virtual N_Port data structure. @@ -1107,6 +1116,8 @@ stop_rr_fcf_flogi: prsp = list_get_first(&pcmd->list, struct lpfc_dmabuf, list); if (!prsp) goto out; + if (!lpfc_is_els_acc_rsp(prsp)) + goto out; sp = prsp->virt + sizeof(uint32_t); /* FLOGI completes successfully */ @@ -2119,6 +2130,10 @@ lpfc_cmpl_els_plogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, /* Good status, call state machine */ prsp = list_entry(cmdiocb->cmd_dmabuf->list.next, struct lpfc_dmabuf, list); + if (!prsp) + goto out; + if (!lpfc_is_els_acc_rsp(prsp)) + goto out; ndlp = lpfc_plogi_confirm_nport(phba, prsp->virt, ndlp); sp = (struct serv_parm *)((u8 *)prsp->virt + @@ -3445,6 +3460,8 @@ lpfc_cmpl_els_disc_cmd(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, prdf = (struct lpfc_els_rdf_rsp *)prsp->virt; if (!prdf) goto out; + if (!lpfc_is_els_acc_rsp(prsp)) + goto out; for (i = 0; i < ELS_RDF_REG_TAG_CNT && i < be32_to_cpu(prdf->reg_d1.reg_desc.count); i++) @@ -4043,6 +4060,9 @@ lpfc_cmpl_els_edc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, edc_rsp->acc_hdr.la_cmd, be32_to_cpu(edc_rsp->desc_list_len)); + if (!lpfc_is_els_acc_rsp(prsp)) + goto out; + /* * Payload length in bytes is the response descriptor list * length minus the 12 bytes of Link Service Request @@ -11339,6 +11359,9 @@ lpfc_cmpl_els_fdisc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, prsp = list_get_first(&pcmd->list, struct lpfc_dmabuf, list); if (!prsp) goto out; + if (!lpfc_is_els_acc_rsp(prsp)) + goto out; + sp = prsp->virt + sizeof(uint32_t); fabric_param_changed = lpfc_check_clean_addr_bit(vport, sp); memcpy(&vport->fabric_portname, &sp->portName, |