|
Daniel Wagner |
192cba |
From: James Smart <jsmart2021@gmail.com>
|
|
Daniel Wagner |
192cba |
Date: Wed, 21 Apr 2021 16:45:11 -0700
|
|
Daniel Wagner |
192cba |
Subject: scsi: lpfc: Fix bad memory access during VPD DUMP mailbox command
|
|
Daniel Wagner |
192cba |
Patch-mainline: v5.13-rc1
|
|
Daniel Wagner |
192cba |
Git-commit: e4ec10228fdf09b88ba018009f14a696fb50d3f2
|
|
Daniel Wagner |
192cba |
References: bsc#1186451
|
|
Daniel Wagner |
192cba |
|
|
Daniel Wagner |
192cba |
The dump command for reading a region passes a requested read length
|
|
Daniel Wagner |
192cba |
specified in words (4-byte units). The response overwrites the same field
|
|
Daniel Wagner |
192cba |
with the actual number of bytes read.
|
|
Daniel Wagner |
192cba |
|
|
Daniel Wagner |
192cba |
The mailbox handler for DUMP which reads VPD data (region 23) is treating
|
|
Daniel Wagner |
192cba |
the response field as if it were still a word_cnt, thus multiplying it by 4
|
|
Daniel Wagner |
192cba |
to set the read's "length". Given the read value was calculated based on
|
|
Daniel Wagner |
192cba |
the size of the read buffer, the longer response length runs off the end of
|
|
Daniel Wagner |
192cba |
the buffer.
|
|
Daniel Wagner |
192cba |
|
|
Daniel Wagner |
192cba |
Fix by reworking the code to use the response field as a byte count.
|
|
Daniel Wagner |
192cba |
|
|
Daniel Wagner |
192cba |
Link: https://lore.kernel.org/r/20210421234511.102206-1-jsmart2021@gmail.com
|
|
Daniel Wagner |
192cba |
Co-developed-by: Justin Tee <justin.tee@broadcom.com>
|
|
Daniel Wagner |
192cba |
Signed-off-by: Justin Tee <justin.tee@broadcom.com>
|
|
Daniel Wagner |
192cba |
Signed-off-by: James Smart <jsmart2021@gmail.com>
|
|
Daniel Wagner |
192cba |
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
|
|
Daniel Wagner |
192cba |
Acked-by: Daniel Wagner <dwagner@suse.de>
|
|
Daniel Wagner |
192cba |
---
|
|
Daniel Wagner |
192cba |
drivers/scsi/lpfc/lpfc_init.c | 12 ++++++------
|
|
Daniel Wagner |
192cba |
drivers/scsi/lpfc/lpfc_sli.c | 15 ++++++++-------
|
|
Daniel Wagner |
192cba |
2 files changed, 14 insertions(+), 13 deletions(-)
|
|
Daniel Wagner |
192cba |
|
|
Daniel Wagner |
192cba |
--- a/drivers/scsi/lpfc/lpfc_init.c
|
|
Daniel Wagner |
192cba |
+++ b/drivers/scsi/lpfc/lpfc_init.c
|
|
Daniel Wagner |
192cba |
@@ -254,13 +254,13 @@ lpfc_config_port_prep(struct lpfc_hba *p
|
|
Daniel Wagner |
192cba |
if (mb->un.varDmp.word_cnt == 0)
|
|
Daniel Wagner |
192cba |
break;
|
|
Daniel Wagner |
192cba |
|
|
Daniel Wagner |
192cba |
- i = mb->un.varDmp.word_cnt * sizeof(uint32_t);
|
|
Daniel Wagner |
192cba |
- if (offset + i > DMP_VPD_SIZE)
|
|
Daniel Wagner |
192cba |
- i = DMP_VPD_SIZE - offset;
|
|
Daniel Wagner |
192cba |
+ if (mb->un.varDmp.word_cnt > DMP_VPD_SIZE - offset)
|
|
Daniel Wagner |
192cba |
+ mb->un.varDmp.word_cnt = DMP_VPD_SIZE - offset;
|
|
Daniel Wagner |
192cba |
lpfc_sli_pcimem_bcopy(((uint8_t *)mb) + DMP_RSP_OFFSET,
|
|
Daniel Wagner |
192cba |
- lpfc_vpd_data + offset, i);
|
|
Daniel Wagner |
192cba |
- offset += i;
|
|
Daniel Wagner |
192cba |
- } while (offset < DMP_VPD_SIZE);
|
|
Daniel Wagner |
192cba |
+ lpfc_vpd_data + offset,
|
|
Daniel Wagner |
192cba |
+ mb->un.varDmp.word_cnt);
|
|
Daniel Wagner |
192cba |
+ offset += mb->un.varDmp.word_cnt;
|
|
Daniel Wagner |
192cba |
+ } while (mb->un.varDmp.word_cnt && offset < DMP_VPD_SIZE);
|
|
Daniel Wagner |
192cba |
|
|
Daniel Wagner |
192cba |
lpfc_parse_vpd(phba, lpfc_vpd_data, offset);
|
|
Daniel Wagner |
192cba |
|
|
Daniel Wagner |
192cba |
--- a/drivers/scsi/lpfc/lpfc_sli.c
|
|
Daniel Wagner |
192cba |
+++ b/drivers/scsi/lpfc/lpfc_sli.c
|
|
Daniel Wagner |
192cba |
@@ -19777,7 +19777,7 @@ lpfc_sli_get_config_region23(struct lpfc
|
|
Daniel Wagner |
192cba |
LPFC_MBOXQ_t *pmb = NULL;
|
|
Daniel Wagner |
192cba |
MAILBOX_t *mb;
|
|
Daniel Wagner |
192cba |
uint32_t offset = 0;
|
|
Daniel Wagner |
192cba |
- int i, rc;
|
|
Daniel Wagner |
192cba |
+ int rc;
|
|
Daniel Wagner |
192cba |
|
|
Daniel Wagner |
192cba |
if (!rgn23_data)
|
|
Daniel Wagner |
192cba |
return 0;
|
|
Daniel Wagner |
192cba |
@@ -19808,13 +19808,14 @@ lpfc_sli_get_config_region23(struct lpfc
|
|
Daniel Wagner |
192cba |
if (mb->un.varDmp.word_cnt == 0)
|
|
Daniel Wagner |
192cba |
break;
|
|
Daniel Wagner |
192cba |
|
|
Daniel Wagner |
192cba |
- i = mb->un.varDmp.word_cnt * sizeof(uint32_t);
|
|
Daniel Wagner |
192cba |
- if (offset + i > DMP_RGN23_SIZE)
|
|
Daniel Wagner |
192cba |
- i = DMP_RGN23_SIZE - offset;
|
|
Daniel Wagner |
192cba |
+ if (mb->un.varDmp.word_cnt > DMP_RGN23_SIZE - offset)
|
|
Daniel Wagner |
192cba |
+ mb->un.varDmp.word_cnt = DMP_RGN23_SIZE - offset;
|
|
Daniel Wagner |
192cba |
+
|
|
Daniel Wagner |
192cba |
lpfc_sli_pcimem_bcopy(((uint8_t *)mb) + DMP_RSP_OFFSET,
|
|
Daniel Wagner |
192cba |
- rgn23_data + offset, i);
|
|
Daniel Wagner |
192cba |
- offset += i;
|
|
Daniel Wagner |
192cba |
- } while (offset < DMP_RGN23_SIZE);
|
|
Daniel Wagner |
192cba |
+ rgn23_data + offset,
|
|
Daniel Wagner |
192cba |
+ mb->un.varDmp.word_cnt);
|
|
Daniel Wagner |
192cba |
+ offset += mb->un.varDmp.word_cnt;
|
|
Daniel Wagner |
192cba |
+ } while (mb->un.varDmp.word_cnt && offset < DMP_RGN23_SIZE);
|
|
Daniel Wagner |
192cba |
|
|
Daniel Wagner |
192cba |
mempool_free(pmb, phba->mbox_mem_pool);
|
|
Daniel Wagner |
192cba |
return offset;
|