Thread (2 messages) 2 messages, 2 authors, 2022-03-30

Re: [PATCH v3] virtio: pci: check bar values read from virtio config space

flat view

From: Jason Wang <hidden>
Date: 2022-03-30 02:44:02
Also in: lkml

On Wed, Mar 23, 2022 at 10:07 PM Keir Fraser [off-list ref] wrote:
virtio pci config structures may in future have non-standard bar
values in the bar field. We should anticipate this by skipping any
structures containing such a reserved value.

The bar value should never change: check for harmful modified values
we re-read it from the config space in vp_modern_map_capability().

Also clean up an existing check to consistently use PCI_STD_NUM_BARS.

Signed-off-by: Keir Fraser <redacted>
Acked-by: Jason Wang <redacted>
quoted hunk
---
 drivers/virtio/virtio_pci_modern.c     | 12 +++++++++---
 drivers/virtio/virtio_pci_modern_dev.c |  9 ++++++++-
 2 files changed, 17 insertions(+), 4 deletions(-)
diff --git a/drivers/virtio/virtio_pci_modern.c b/drivers/virtio/virtio_pci_modern.c
index 5455bc041fb6..6adfcd0297a7 100644
--- a/drivers/virtio/virtio_pci_modern.c
+++ b/drivers/virtio/virtio_pci_modern.c
@@ -293,7 +293,7 @@ static int virtio_pci_find_shm_cap(struct pci_dev *dev, u8 required_id,

        for (pos = pci_find_capability(dev, PCI_CAP_ID_VNDR); pos > 0;
             pos = pci_find_next_capability(dev, pos, PCI_CAP_ID_VNDR)) {
-               u8 type, cap_len, id;
+               u8 type, cap_len, id, res_bar;
                u32 tmp32;
                u64 res_offset, res_length;
@@ -315,9 +315,14 @@ static int virtio_pci_find_shm_cap(struct pci_dev *dev, u8 required_id,
                if (id != required_id)
                        continue;

-               /* Type, and ID match, looks good */
                pci_read_config_byte(dev, pos + offsetof(struct virtio_pci_cap,
-                                                        bar), bar);
+                                                        bar), &res_bar);
+               if (res_bar >= PCI_STD_NUM_BARS)
+                       continue;
+
+               /* Type and ID match, and the BAR value isn't reserved.
+                * Looks good.
+                */

                /* Read the lower 32bit of length and offset */
                pci_read_config_dword(dev, pos + offsetof(struct virtio_pci_cap,
@@ -337,6 +342,7 @@ static int virtio_pci_find_shm_cap(struct pci_dev *dev, u8 required_id,
                                                     length_hi), &tmp32);
                res_length |= ((u64)tmp32) << 32;

+               *bar = res_bar;
                *offset = res_offset;
                *len = res_length;
diff --git a/drivers/virtio/virtio_pci_modern_dev.c b/drivers/virtio/virtio_pci_modern_dev.c
index e8b3ff2b9fbc..591738ad3d56 100644
--- a/drivers/virtio/virtio_pci_modern_dev.c
+++ b/drivers/virtio/virtio_pci_modern_dev.c
@@ -35,6 +35,13 @@ vp_modern_map_capability(struct virtio_pci_modern_device *mdev, int off,
        pci_read_config_dword(dev, off + offsetof(struct virtio_pci_cap, length),
                              &length);

+       /* Check if the BAR may have changed since we requested the region. */
+       if (bar >= PCI_STD_NUM_BARS || !(mdev->modern_bars & (1 << bar))) {
+               dev_err(&dev->dev,
+                       "virtio_pci: bar unexpectedly changed to %u\n", bar);
+               return NULL;
+       }
+
        if (length <= start) {
                dev_err(&dev->dev,
                        "virtio_pci: bad capability len %u (>%u expected)\n",
@@ -120,7 +127,7 @@ static inline int virtio_pci_find_capability(struct pci_dev *dev, u8 cfg_type,
                                     &bar);

                /* Ignore structures with reserved BAR values */
-               if (bar > 0x5)
+               if (bar >= PCI_STD_NUM_BARS)
                        continue;

                if (type == cfg_type) {
--
2.35.1.894.gb6a874cedc-goog
_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help