diff options
Diffstat (limited to 'drivers/vfio/pci/vfio_pci.c')
-rw-r--r-- | drivers/vfio/pci/vfio_pci.c | 33 |
1 files changed, 21 insertions, 12 deletions
diff --git a/drivers/vfio/pci/vfio_pci.c b/drivers/vfio/pci/vfio_pci.c index d624a527777f..031bc08d000d 100644 --- a/drivers/vfio/pci/vfio_pci.c +++ b/drivers/vfio/pci/vfio_pci.c | |||
@@ -829,8 +829,9 @@ static long vfio_pci_ioctl(void *device_data, | |||
829 | 829 | ||
830 | } else if (cmd == VFIO_DEVICE_SET_IRQS) { | 830 | } else if (cmd == VFIO_DEVICE_SET_IRQS) { |
831 | struct vfio_irq_set hdr; | 831 | struct vfio_irq_set hdr; |
832 | size_t size; | ||
832 | u8 *data = NULL; | 833 | u8 *data = NULL; |
833 | int ret = 0; | 834 | int max, ret = 0; |
834 | 835 | ||
835 | minsz = offsetofend(struct vfio_irq_set, count); | 836 | minsz = offsetofend(struct vfio_irq_set, count); |
836 | 837 | ||
@@ -838,23 +839,31 @@ static long vfio_pci_ioctl(void *device_data, | |||
838 | return -EFAULT; | 839 | return -EFAULT; |
839 | 840 | ||
840 | if (hdr.argsz < minsz || hdr.index >= VFIO_PCI_NUM_IRQS || | 841 | if (hdr.argsz < minsz || hdr.index >= VFIO_PCI_NUM_IRQS || |
842 | hdr.count >= (U32_MAX - hdr.start) || | ||
841 | hdr.flags & ~(VFIO_IRQ_SET_DATA_TYPE_MASK | | 843 | hdr.flags & ~(VFIO_IRQ_SET_DATA_TYPE_MASK | |
842 | VFIO_IRQ_SET_ACTION_TYPE_MASK)) | 844 | VFIO_IRQ_SET_ACTION_TYPE_MASK)) |
843 | return -EINVAL; | 845 | return -EINVAL; |
844 | 846 | ||
845 | if (!(hdr.flags & VFIO_IRQ_SET_DATA_NONE)) { | 847 | max = vfio_pci_get_irq_count(vdev, hdr.index); |
846 | size_t size; | 848 | if (hdr.start >= max || hdr.start + hdr.count > max) |
847 | int max = vfio_pci_get_irq_count(vdev, hdr.index); | 849 | return -EINVAL; |
848 | 850 | ||
849 | if (hdr.flags & VFIO_IRQ_SET_DATA_BOOL) | 851 | switch (hdr.flags & VFIO_IRQ_SET_DATA_TYPE_MASK) { |
850 | size = sizeof(uint8_t); | 852 | case VFIO_IRQ_SET_DATA_NONE: |
851 | else if (hdr.flags & VFIO_IRQ_SET_DATA_EVENTFD) | 853 | size = 0; |
852 | size = sizeof(int32_t); | 854 | break; |
853 | else | 855 | case VFIO_IRQ_SET_DATA_BOOL: |
854 | return -EINVAL; | 856 | size = sizeof(uint8_t); |
857 | break; | ||
858 | case VFIO_IRQ_SET_DATA_EVENTFD: | ||
859 | size = sizeof(int32_t); | ||
860 | break; | ||
861 | default: | ||
862 | return -EINVAL; | ||
863 | } | ||
855 | 864 | ||
856 | if (hdr.argsz - minsz < hdr.count * size || | 865 | if (size) { |
857 | hdr.start >= max || hdr.start + hdr.count > max) | 866 | if (hdr.argsz - minsz < hdr.count * size) |
858 | return -EINVAL; | 867 | return -EINVAL; |
859 | 868 | ||
860 | data = memdup_user((void __user *)(arg + minsz), | 869 | data = memdup_user((void __user *)(arg + minsz), |