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:
parent
b59c489750
commit
1d831cd3a2
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
Loading…
Reference in New Issue