diff options
author | James Smart <jsmart2021@gmail.com> | 2021-04-21 16:45:11 -0700 |
---|---|---|
committer | Martin K. Petersen <martin.petersen@oracle.com> | 2021-04-26 22:58:38 -0400 |
commit | e4ec10228fdf09b88ba018009f14a696fb50d3f2 (patch) | |
tree | a5cc7732965c7efd6f028c389f418cfbbe077221 /drivers/scsi | |
parent | 83adbba746d1c8b6e3b07d73ae7815044804c96e (diff) | |
download | linux-e4ec10228fdf09b88ba018009f14a696fb50d3f2.tar.bz2 |
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>
Diffstat (limited to 'drivers/scsi')
-rw-r--r-- | drivers/scsi/lpfc/lpfc_init.c | 12 | ||||
-rw-r--r-- | drivers/scsi/lpfc/lpfc_sli.c | 15 |
2 files changed, 14 insertions, 13 deletions
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 1e4c792bb660..5f018d02bf56 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c @@ -254,13 +254,13 @@ lpfc_config_port_prep(struct lpfc_hba *phba) if (mb->un.varDmp.word_cnt == 0) break; - i = mb->un.varDmp.word_cnt * sizeof(uint32_t); - if (offset + i > DMP_VPD_SIZE) - i = DMP_VPD_SIZE - offset; + if (mb->un.varDmp.word_cnt > DMP_VPD_SIZE - offset) + mb->un.varDmp.word_cnt = DMP_VPD_SIZE - offset; lpfc_sli_pcimem_bcopy(((uint8_t *)mb) + DMP_RSP_OFFSET, - lpfc_vpd_data + offset, i); - offset += i; - } while (offset < DMP_VPD_SIZE); + lpfc_vpd_data + offset, + mb->un.varDmp.word_cnt); + offset += mb->un.varDmp.word_cnt; + } while (mb->un.varDmp.word_cnt && offset < DMP_VPD_SIZE); lpfc_parse_vpd(phba, lpfc_vpd_data, offset); diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c index 579ac75dfe79..573c8599d71c 100644 --- a/drivers/scsi/lpfc/lpfc_sli.c +++ b/drivers/scsi/lpfc/lpfc_sli.c @@ -19777,7 +19777,7 @@ lpfc_sli_get_config_region23(struct lpfc_hba *phba, char *rgn23_data) LPFC_MBOXQ_t *pmb = NULL; MAILBOX_t *mb; uint32_t offset = 0; - int i, rc; + int rc; if (!rgn23_data) 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) break; - i = mb->un.varDmp.word_cnt * sizeof(uint32_t); - if (offset + i > DMP_RGN23_SIZE) - i = DMP_RGN23_SIZE - offset; + if (mb->un.varDmp.word_cnt > DMP_RGN23_SIZE - offset) + mb->un.varDmp.word_cnt = DMP_RGN23_SIZE - offset; + lpfc_sli_pcimem_bcopy(((uint8_t *)mb) + DMP_RSP_OFFSET, - rgn23_data + offset, i); - offset += i; - } while (offset < DMP_RGN23_SIZE); + rgn23_data + offset, + mb->un.varDmp.word_cnt); + offset += mb->un.varDmp.word_cnt; + } while (mb->un.varDmp.word_cnt && offset < DMP_RGN23_SIZE); mempool_free(pmb, phba->mbox_mem_pool); return offset; |