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>
This commit is contained in:
parent
12e896c742
commit
a3c3c0a806
1 changed files with 23 additions and 0 deletions
|
@ -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 @@ stop_rr_fcf_flogi:
|
||||||
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,
|
||||||
/* 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,
|
||||||
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,
|
||||||
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,
|
||||||
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,
|
||||||
|
|
Loading…
Add table
Reference in a new issue