aboutsummaryrefslogtreecommitdiff
path: root/drivers/virtio
diff options
context:
space:
mode:
authorAndrew Scull2022-04-21 16:11:03 +0000
committerTom Rini2022-05-03 15:50:45 -0400
commitf2c1ef1b6dfe93e9912d5d5dfae1e527da511c3f (patch)
tree77e309d5c02e5ccfedf38223861f46ff9ccd8f37 /drivers/virtio
parentc690f64f4c958531fb4bb1b1540931adba022830 (diff)
virtio: pci: Check virtio common config size
Check that the common config is at least as large as the struct it is expected to contain. Only then is it safe to cast the pointer and be safe from out-of-bounds accesses. Signed-off-by: Andrew Scull <ascull@google.com> Reviewed-by: Bin Meng <bmeng.cn@gmail.com>
Diffstat (limited to 'drivers/virtio')
-rw-r--r--drivers/virtio/virtio_pci_modern.c8
1 files changed, 8 insertions, 0 deletions
diff --git a/drivers/virtio/virtio_pci_modern.c b/drivers/virtio/virtio_pci_modern.c
index 7dd58aa0f42..2c1b0ebfce6 100644
--- a/drivers/virtio/virtio_pci_modern.c
+++ b/drivers/virtio/virtio_pci_modern.c
@@ -480,6 +480,7 @@ static int virtio_pci_probe(struct udevice *udev)
u16 subvendor;
u8 revision;
int common, notify, device;
+ u32 common_length;
int offset;
/* We only own devices >= 0x1040 and <= 0x107f: leave the rest. */
@@ -501,6 +502,13 @@ static int virtio_pci_probe(struct udevice *udev)
return -ENODEV;
}
+ offset = common + offsetof(struct virtio_pci_cap, length);
+ dm_pci_read_config32(udev, offset, &common_length);
+ if (common_length < sizeof(struct virtio_pci_common_cfg)) {
+ printf("(%s): virtio common config too small\n", udev->name);
+ return -EINVAL;
+ }
+
/* If common is there, notify should be too */
notify = virtio_pci_find_capability(udev, VIRTIO_PCI_CAP_NOTIFY_CFG);
if (!notify) {