diff mbox series

[REPOST] lpfc: Fix bad memory access during VPD DUMP mailbox command

Message ID 20210421234511.102206-1-jsmart2021@gmail.com (mailing list archive)
State Accepted
Commit e4ec10228fdf09b88ba018009f14a696fb50d3f2
Headers show
Series [REPOST] lpfc: Fix bad memory access during VPD DUMP mailbox command | expand

Commit Message

James Smart April 21, 2021, 11:45 p.m. UTC
The dump command for reading a region passes a requested read length
specified in words (4byte 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.

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>

---
 drivers/scsi/lpfc/lpfc_init.c | 12 ++++++------
 drivers/scsi/lpfc/lpfc_sli.c  | 15 ++++++++-------
 2 files changed, 14 insertions(+), 13 deletions(-)

Comments

Martin K. Petersen April 27, 2021, 3:07 a.m. UTC | #1
On Wed, 21 Apr 2021 16:45:11 -0700, James Smart wrote:

> The dump command for reading a region passes a requested read length
> specified in words (4byte 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.
> 
> [...]

Applied to 5.13/scsi-fixes, thanks!

[1/1] lpfc: Fix bad memory access during VPD DUMP mailbox command
      https://git.kernel.org/mkp/scsi/c/e4ec10228fdf
Martin K. Petersen April 29, 2021, 3:18 a.m. UTC | #2
On Wed, 21 Apr 2021 16:45:11 -0700, James Smart wrote:

> The dump command for reading a region passes a requested read length
> specified in words (4byte 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.
> 
> [...]

Applied to 5.13/scsi-fixes, thanks!

[1/1] lpfc: Fix bad memory access during VPD DUMP mailbox command
      https://git.kernel.org/mkp/scsi/c/e4ec10228fdf
diff mbox series

Patch

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;