]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
util: validate pcie_cap_pos != 0 in virDeviceHasPCIExpressLink()
authorLaine Stump <laine@redhat.com>
Wed, 6 Jan 2021 20:42:47 +0000 (15:42 -0500)
committerLaine Stump <laine@redhat.com>
Fri, 8 Jan 2021 00:41:27 +0000 (19:41 -0500)
virDeviceHasPCIExpressLink() wasn't checking that pcie_cap_pos was
valid before attempting to use it, which could lead to reading the
byte at offset 0 + PCI_CAP_ID_EXP instead of [valid offset] +
PCI_CAP_ID_EXP. In particular, this could happen for "integrated" PCI
devices (those that are on the PCIe root complex). If it happened that
the byte from the wrong address had the "right" bit set, then it would
lead to us innappropriately believing that Express Link info was
available when it wasn't, and the node device driver would then log an
error like this:

  virPCIDeviceGetLinkCapSta:2754 :
  internal error: pci device 0000:00:18.0 is not a PCI-Express device

during a libvirtd restart. (this didn't ever occur until after
virPCIDeviceIsPCIExpress() was made more intelligent in commit
c00b6b1ae, which hasn't yet been in any official release)

Signed-off-by: Laine Stump <laine@redhat.com>
Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
src/util/virpci.c

index 9bfc743fbd92ca8bc54e9f53f75c47fe18145bce..50fd5ef7ea3a859a509950187a1d7d8a9dad3ce6 100644 (file)
@@ -2722,6 +2722,11 @@ virPCIDeviceHasPCIExpressLink(virPCIDevicePtr dev)
     if (virPCIDeviceInit(dev, fd) < 0)
         goto cleanup;
 
+    if (dev->pcie_cap_pos == 0) {
+        ret = 0;
+        goto cleanup;
+    }
+
     cap = virPCIDeviceRead16(dev, fd, dev->pcie_cap_pos + PCI_CAP_FLAGS);
     type = (cap & PCI_EXP_FLAGS_TYPE) >> 4;