summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDick Kennedy <dick.kennedy@broadcom.com>2020-06-30 23:49:52 +0200
committerMartin K. Petersen <martin.petersen@oracle.com>2020-07-03 05:06:36 +0200
commitd91e3abb682b07b04ced3f3d363651abedcb0309 (patch)
tree3de8e2316eac1b5f779e4b83a77c9b1ef4442d16
parentscsi: lpfc: Fix NVMe rport deregister and registration during ADISC (diff)
downloadlinux-d91e3abb682b07b04ced3f3d363651abedcb0309.tar.xz
linux-d91e3abb682b07b04ced3f3d363651abedcb0309.zip
scsi: lpfc: Fix oops due to overrun when reading SLI3 data
When using DUMP on SLI3 to read VPD and Port status data (config region 23), the adapter is overruning the kmalloc'd buffer causing havoc on other consumers of the allocation pools. Rework the loops processing the dump data and validate/size memory lengths before performing bcopy. Link: https://lore.kernel.org/r/20200630215001.70793-6-jsmart2021@gmail.com Signed-off-by: Dick Kennedy <dick.kennedy@broadcom.com> Signed-off-by: James Smart <jsmart2021@gmail.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
-rw-r--r--drivers/scsi/lpfc/lpfc_init.c14
-rw-r--r--drivers/scsi/lpfc/lpfc_sli.c14
2 files changed, 15 insertions, 13 deletions
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c
index 69a5249e007a..287a78185dc7 100644
--- a/drivers/scsi/lpfc/lpfc_init.c
+++ b/drivers/scsi/lpfc/lpfc_init.c
@@ -253,13 +253,15 @@ lpfc_config_port_prep(struct lpfc_hba *phba)
*/
if (mb->un.varDmp.word_cnt == 0)
break;
- if (mb->un.varDmp.word_cnt > DMP_VPD_SIZE - offset)
- mb->un.varDmp.word_cnt = DMP_VPD_SIZE - offset;
+
+ i = mb->un.varDmp.word_cnt * sizeof(uint32_t);
+ if (offset + i > DMP_VPD_SIZE)
+ i = DMP_VPD_SIZE - offset;
lpfc_sli_pcimem_bcopy(((uint8_t *)mb) + DMP_RSP_OFFSET,
- 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_vpd_data + offset, i);
+ offset += i;
+ } while (offset < DMP_VPD_SIZE);
+
lpfc_parse_vpd(phba, lpfc_vpd_data, offset);
kfree(lpfc_vpd_data);
diff --git a/drivers/scsi/lpfc/lpfc_sli.c b/drivers/scsi/lpfc/lpfc_sli.c
index 1575fccc8b0c..cefc3cbb69ae 100644
--- a/drivers/scsi/lpfc/lpfc_sli.c
+++ b/drivers/scsi/lpfc/lpfc_sli.c
@@ -19326,7 +19326,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 rc;
+ int i, rc;
if (!rgn23_data)
return 0;
@@ -19356,14 +19356,14 @@ lpfc_sli_get_config_region23(struct lpfc_hba *phba, char *rgn23_data)
*/
if (mb->un.varDmp.word_cnt == 0)
break;
- if (mb->un.varDmp.word_cnt > DMP_RGN23_SIZE - offset)
- mb->un.varDmp.word_cnt = DMP_RGN23_SIZE - offset;
+ i = mb->un.varDmp.word_cnt * sizeof(uint32_t);
+ if (offset + i > DMP_RGN23_SIZE)
+ i = DMP_RGN23_SIZE - offset;
lpfc_sli_pcimem_bcopy(((uint8_t *)mb) + DMP_RSP_OFFSET,
- rgn23_data + offset,
- mb->un.varDmp.word_cnt);
- offset += mb->un.varDmp.word_cnt;
- } while (mb->un.varDmp.word_cnt && offset < DMP_RGN23_SIZE);
+ rgn23_data + offset, i);
+ offset += i;
+ } while (offset < DMP_RGN23_SIZE);
mempool_free(pmb, phba->mbox_mem_pool);
return offset;