Commit a3c3c0a8 authored by Justin Tee's avatar Justin Tee Committed by Martin K. Petersen

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: default avatarJustin Tee <justin.tee@broadcom.com>
Link: https://lore.kernel.org/r/20231009161812.97232-5-justintee8345@gmail.comSigned-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent 12e896c7
...@@ -131,6 +131,15 @@ lpfc_els_chk_latt(struct lpfc_vport *vport) ...@@ -131,6 +131,15 @@ lpfc_els_chk_latt(struct lpfc_vport *vport)
return 1; 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 * lpfc_prep_els_iocb - Allocate and prepare a lpfc iocb data structure
* @vport: pointer to a host virtual N_Port data structure. * @vport: pointer to a host virtual N_Port data structure.
...@@ -1107,6 +1116,8 @@ lpfc_cmpl_els_flogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, ...@@ -1107,6 +1116,8 @@ lpfc_cmpl_els_flogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
prsp = list_get_first(&pcmd->list, struct lpfc_dmabuf, list); prsp = list_get_first(&pcmd->list, struct lpfc_dmabuf, list);
if (!prsp) if (!prsp)
goto out; goto out;
if (!lpfc_is_els_acc_rsp(prsp))
goto out;
sp = prsp->virt + sizeof(uint32_t); sp = prsp->virt + sizeof(uint32_t);
/* FLOGI completes successfully */ /* FLOGI completes successfully */
...@@ -2119,6 +2130,10 @@ lpfc_cmpl_els_plogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, ...@@ -2119,6 +2130,10 @@ lpfc_cmpl_els_plogi(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
/* Good status, call state machine */ /* Good status, call state machine */
prsp = list_entry(cmdiocb->cmd_dmabuf->list.next, prsp = list_entry(cmdiocb->cmd_dmabuf->list.next,
struct lpfc_dmabuf, list); 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); ndlp = lpfc_plogi_confirm_nport(phba, prsp->virt, ndlp);
sp = (struct serv_parm *)((u8 *)prsp->virt + sp = (struct serv_parm *)((u8 *)prsp->virt +
...@@ -3445,6 +3460,8 @@ lpfc_cmpl_els_disc_cmd(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb, ...@@ -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; prdf = (struct lpfc_els_rdf_rsp *)prsp->virt;
if (!prdf) if (!prdf)
goto out; goto out;
if (!lpfc_is_els_acc_rsp(prsp))
goto out;
for (i = 0; i < ELS_RDF_REG_TAG_CNT && for (i = 0; i < ELS_RDF_REG_TAG_CNT &&
i < be32_to_cpu(prdf->reg_d1.reg_desc.count); i++) 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, ...@@ -4043,6 +4060,9 @@ lpfc_cmpl_els_edc(struct lpfc_hba *phba, struct lpfc_iocbq *cmdiocb,
edc_rsp->acc_hdr.la_cmd, edc_rsp->acc_hdr.la_cmd,
be32_to_cpu(edc_rsp->desc_list_len)); 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 * Payload length in bytes is the response descriptor list
* length minus the 12 bytes of Link Service Request * 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, ...@@ -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); prsp = list_get_first(&pcmd->list, struct lpfc_dmabuf, list);
if (!prsp) if (!prsp)
goto out; goto out;
if (!lpfc_is_els_acc_rsp(prsp))
goto out;
sp = prsp->virt + sizeof(uint32_t); sp = prsp->virt + sizeof(uint32_t);
fabric_param_changed = lpfc_check_clean_addr_bit(vport, sp); fabric_param_changed = lpfc_check_clean_addr_bit(vport, sp);
memcpy(&vport->fabric_portname, &sp->portName, memcpy(&vport->fabric_portname, &sp->portName,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment