diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-11-01 18:52:56 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-11-01 18:52:56 -0400 |
commit | a75e0032684d5ad9465f68d54b9d7337790b4ef2 (patch) | |
tree | c82ce2d7bd57c719df80a6c4ec813cbd7d228e85 | |
parent | 0c183d92b20b5c84ca655b45ef57b3318b83eb9e (diff) | |
parent | 05692d7005a364add85c6e25a6c4447ce08f913a (diff) |
Merge tag 'vfio-v4.9-rc4' of git://github.com/awilliam/linux-vfio
Pull VFIO fix from Alex Williamson:
"SET_IRQS ioctl parameter sanitization (Vlad Tsyrklevich)"
* tag 'vfio-v4.9-rc4' of git://github.com/awilliam/linux-vfio:
vfio/pci: Fix integer overflows, bitmask check
-rw-r--r-- | drivers/vfio/pci/vfio_pci.c | 33 | ||||
-rw-r--r-- | drivers/vfio/pci/vfio_pci_intrs.c | 2 |
2 files changed, 22 insertions, 13 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), |
diff --git a/drivers/vfio/pci/vfio_pci_intrs.c b/drivers/vfio/pci/vfio_pci_intrs.c index c2e60893cd09..1c46045b0e7f 100644 --- a/drivers/vfio/pci/vfio_pci_intrs.c +++ b/drivers/vfio/pci/vfio_pci_intrs.c | |||
@@ -256,7 +256,7 @@ static int vfio_msi_enable(struct vfio_pci_device *vdev, int nvec, bool msix) | |||
256 | if (!is_irq_none(vdev)) | 256 | if (!is_irq_none(vdev)) |
257 | return -EINVAL; | 257 | return -EINVAL; |
258 | 258 | ||
259 | vdev->ctx = kzalloc(nvec * sizeof(struct vfio_pci_irq_ctx), GFP_KERNEL); | 259 | vdev->ctx = kcalloc(nvec, sizeof(struct vfio_pci_irq_ctx), GFP_KERNEL); |
260 | if (!vdev->ctx) | 260 | if (!vdev->ctx) |
261 | return -ENOMEM; | 261 | return -ENOMEM; |
262 | 262 | ||