Commit d91e3abb authored by Dick Kennedy's avatar Dick Kennedy Committed by Martin K. Petersen

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.comSigned-off-by: default avatarDick Kennedy <dick.kennedy@broadcom.com>
Signed-off-by: default avatarJames Smart <jsmart2021@gmail.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent 9806c984
......@@ -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);
......
......@@ -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;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment