scsi: lpfc: Fix bad memory access during VPD DUMP mailbox command
The dump command for reading a region passes a requested read length specified in words (4-byte units). The response overwrites the same field with the actual number of bytes read. The mailbox handler for DUMP which reads VPD data (region 23) is treating the response field as if it were still a word_cnt, thus multiplying it by 4 to set the read's "length". Given the read value was calculated based on the size of the read buffer, the longer response length runs off the end of the buffer. Fix by reworking the code to use the response field as a byte count. Link: https://lore.kernel.org/r/20210421234511.102206-1-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>
This commit is contained in:
parent
83adbba746
commit
e4ec10228f
@ -254,13 +254,13 @@ lpfc_config_port_prep(struct lpfc_hba *phba)
|
|||||||
if (mb->un.varDmp.word_cnt == 0)
|
if (mb->un.varDmp.word_cnt == 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
i = mb->un.varDmp.word_cnt * sizeof(uint32_t);
|
if (mb->un.varDmp.word_cnt > DMP_VPD_SIZE - offset)
|
||||||
if (offset + i > DMP_VPD_SIZE)
|
mb->un.varDmp.word_cnt = DMP_VPD_SIZE - offset;
|
||||||
i = DMP_VPD_SIZE - offset;
|
|
||||||
lpfc_sli_pcimem_bcopy(((uint8_t *)mb) + DMP_RSP_OFFSET,
|
lpfc_sli_pcimem_bcopy(((uint8_t *)mb) + DMP_RSP_OFFSET,
|
||||||
lpfc_vpd_data + offset, i);
|
lpfc_vpd_data + offset,
|
||||||
offset += i;
|
mb->un.varDmp.word_cnt);
|
||||||
} while (offset < DMP_VPD_SIZE);
|
offset += mb->un.varDmp.word_cnt;
|
||||||
|
} while (mb->un.varDmp.word_cnt && offset < DMP_VPD_SIZE);
|
||||||
|
|
||||||
lpfc_parse_vpd(phba, lpfc_vpd_data, offset);
|
lpfc_parse_vpd(phba, lpfc_vpd_data, offset);
|
||||||
|
|
||||||
|
@ -19777,7 +19777,7 @@ lpfc_sli_get_config_region23(struct lpfc_hba *phba, char *rgn23_data)
|
|||||||
LPFC_MBOXQ_t *pmb = NULL;
|
LPFC_MBOXQ_t *pmb = NULL;
|
||||||
MAILBOX_t *mb;
|
MAILBOX_t *mb;
|
||||||
uint32_t offset = 0;
|
uint32_t offset = 0;
|
||||||
int i, rc;
|
int rc;
|
||||||
|
|
||||||
if (!rgn23_data)
|
if (!rgn23_data)
|
||||||
return 0;
|
return 0;
|
||||||
@ -19808,13 +19808,14 @@ lpfc_sli_get_config_region23(struct lpfc_hba *phba, char *rgn23_data)
|
|||||||
if (mb->un.varDmp.word_cnt == 0)
|
if (mb->un.varDmp.word_cnt == 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
i = mb->un.varDmp.word_cnt * sizeof(uint32_t);
|
if (mb->un.varDmp.word_cnt > DMP_RGN23_SIZE - offset)
|
||||||
if (offset + i > DMP_RGN23_SIZE)
|
mb->un.varDmp.word_cnt = DMP_RGN23_SIZE - offset;
|
||||||
i = DMP_RGN23_SIZE - offset;
|
|
||||||
lpfc_sli_pcimem_bcopy(((uint8_t *)mb) + DMP_RSP_OFFSET,
|
lpfc_sli_pcimem_bcopy(((uint8_t *)mb) + DMP_RSP_OFFSET,
|
||||||
rgn23_data + offset, i);
|
rgn23_data + offset,
|
||||||
offset += i;
|
mb->un.varDmp.word_cnt);
|
||||||
} while (offset < DMP_RGN23_SIZE);
|
offset += mb->un.varDmp.word_cnt;
|
||||||
|
} while (mb->un.varDmp.word_cnt && offset < DMP_RGN23_SIZE);
|
||||||
|
|
||||||
mempool_free(pmb, phba->mbox_mem_pool);
|
mempool_free(pmb, phba->mbox_mem_pool);
|
||||||
return offset;
|
return offset;
|
||||||
|
Loading…
Reference in New Issue
Block a user