scsi: lpfc: Fix oops due to overrun when reading SLI3 data
authorDick Kennedy <dick.kennedy@broadcom.com>
Tue, 30 Jun 2020 21:49:52 +0000 (14:49 -0700)
committerMartin K. Petersen <martin.petersen@oracle.com>
Fri, 3 Jul 2020 03:06:36 +0000 (23:06 -0400)
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>
drivers/scsi/lpfc/lpfc_init.c
drivers/scsi/lpfc/lpfc_sli.c

index 69a5249e007a3e1270b972964aa17a3f83cc6518..287a78185dc77cb0482062d11b64d7b708b79d75 100644 (file)
@@ -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);
index 1575fccc8b0ce1964a1f9d34ef46910bd38f6b6d..cefc3cbb69ae7434856b33e35c6aa72745cce36f 100644 (file)
@@ -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;