Skip to content

Commit

Permalink
scsi: lpfc: Fix bad memory access during VPD DUMP mailbox command
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
James Smart authored and Martin K. Petersen committed Apr 27, 2021
1 parent 83adbba commit e4ec102
Show file tree
Hide file tree
Showing 2 changed files with 14 additions and 13 deletions.
12 changes: 6 additions & 6 deletions drivers/scsi/lpfc/lpfc_init.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
15 changes: 8 additions & 7 deletions drivers/scsi/lpfc/lpfc_sli.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down

0 comments on commit e4ec102

Please sign in to comment.