hv: Add checks in pci_enumerate_ext_cap to guard against malformed lists

In pci_enumerate_ext_cap we assume the extended capability linked lists
are always legal and correct, which might not be true when there was a
faulty hardware. This patch adds checks (time to live) to guard against malformed
extended capability linked lists.

v2:
Add error printing when node_limit <= 0.

Tracked-On: #6571
Signed-off-by: Yifan Liu <yifan1.liu@intel.com>
Reviewed-by: Wang, Yu1 <yu1.wang@intel.com>
Acked-by: Anthony Xu <anthony.xu@intel.com>
This commit is contained in:
Yifan Liu 2021-11-02 09:27:27 +08:00 committed by wenlingz
parent b59c489750
commit 1d831cd3a2
1 changed files with 19 additions and 1 deletions

View File

@ -726,11 +726,17 @@ static void pci_enumerate_ext_cap(struct pci_pdev *pdev)
uint32_t hdr, pos, pre_pos = 0U;
uint8_t pcie_dev_type;
/* guard against malformed list */
int node_limit;
pos = PCI_ECAP_BASE_PTR;
/* minimum 8 bytes per cap */
node_limit = (PCIE_CONFIG_SPACE_SIZE - PCI_CONFIG_SPACE_SIZE) / 8;
/* PCI Express Extended Capability must have 4 bytes header */
hdr = pci_pdev_read_cfg(pdev->bdf, pos, 4U);
while (hdr != 0U) {
while ((hdr != 0U) && (node_limit > 0)) {
if (PCI_ECAP_ID(hdr) == PCIZ_SRIOV) {
pdev->sriov.capoff = pos;
pdev->sriov.caplen = PCI_SRIOV_CAP_LEN;
@ -767,8 +773,20 @@ static void pci_enumerate_ext_cap(struct pci_pdev *pdev)
if (pos == 0U) {
break;
}
if (pos < PCI_CONFIG_SPACE_SIZE) {
pr_err("pdev %x:%x.%x: Illegal PCIe extended capability offset %x",
pdev->bdf.bits.b, pdev->bdf.bits.d, pdev->bdf.bits.f, pos);
break;
}
hdr = pci_pdev_read_cfg(pdev->bdf, pos, 4U);
node_limit--;
};
if (node_limit <= 0) {
pr_err("%s: pdev[%x:%x.%x] Malformed linked list in PCIe extended \
capability region detected\n", __func__, pdev->bdf.bits.b,
pdev->bdf.bits.d, pdev->bdf.bits.f);
}
}
/*