Now, the function vp_modern_map_capability() takes the size parameter, which corresponds to the size of virtio_pci_common_cfg. As a result, this indicates the size of memory area to map.
However, if the _F_RING_RESET is negotiated, the extra items will be used. Therefore, we need to use the size of virtio_pci_modre_common_cfg to map more space. Meanwhile, this patch checks the common cfg size when _F_RING_ERSET is negotiated. Signed-off-by: Xuan Zhuo <xuanz...@linux.alibaba.com> --- drivers/virtio/virtio_pci_modern_dev.c | 27 ++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/drivers/virtio/virtio_pci_modern_dev.c b/drivers/virtio/virtio_pci_modern_dev.c index aad7d9296e77..45d41e6c7799 100644 --- a/drivers/virtio/virtio_pci_modern_dev.c +++ b/drivers/virtio/virtio_pci_modern_dev.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-or-later #include <linux/virtio_pci_modern.h> +#include <linux/virtio_config.h> #include <linux/module.h> #include <linux/pci.h> #include <linux/delay.h> @@ -142,6 +143,22 @@ static inline int virtio_pci_find_capability(struct pci_dev *dev, u8 cfg_type, return 0; } +static inline int check_common_size(struct virtio_pci_modern_device *mdev, + size_t common_len) +{ + u64 features; + + features = vp_modern_get_features(mdev); + + if (features & BIT_ULL(VIRTIO_F_RING_RESET)) { + if (unlikely(common_len < offsetofend(struct virtio_pci_modern_common_cfg, + queue_reset))) + return -ENOENT; + } + + return 0; +} + /* This is part of the ABI. Don't screw with it. */ static inline void check_offsets(void) { @@ -218,6 +235,7 @@ int vp_modern_probe(struct virtio_pci_modern_device *mdev) int err, common, isr, notify, device; u32 notify_length; u32 notify_offset; + size_t common_len; int devid; check_offsets(); @@ -291,10 +309,14 @@ int vp_modern_probe(struct virtio_pci_modern_device *mdev) err = -EINVAL; mdev->common = vp_modern_map_capability(mdev, common, sizeof(struct virtio_pci_common_cfg), 4, - 0, sizeof(struct virtio_pci_common_cfg), - NULL, NULL); + 0, sizeof(struct virtio_pci_modern_common_cfg), + &common_len, NULL); if (!mdev->common) goto err_map_common; + + if (check_common_size(mdev, common_len)) + goto err_common_size; + mdev->isr = vp_modern_map_capability(mdev, isr, sizeof(u8), 1, 0, 1, NULL, NULL); @@ -353,6 +375,7 @@ int vp_modern_probe(struct virtio_pci_modern_device *mdev) err_map_notify: pci_iounmap(pci_dev, mdev->isr); err_map_isr: +err_common_size: pci_iounmap(pci_dev, mdev->common); err_map_common: pci_release_selected_regions(pci_dev, mdev->modern_bars); -- 2.32.0.3.g01195cf9f _______________________________________________ Virtualization mailing list Virtualization@lists.linux-foundation.org https://lists.linuxfoundation.org/mailman/listinfo/virtualization