Add error handling for the following VFIO_DEVICE_SET_IRQS cases with
respect to the hdr struct:

- More than one VFIO_IRQ_DATA_TYPE_MASK flag is set in hdr.flags
- More than one VFIO_IRQ_ACTION_TYPE_MASK flag is set in hdr.flags
- hdr.count is not specified

Note that since hdr.count != 0, data_size != 0 is guaranteed unless
vfio_set_irqs_validate_and_prepare fails and returns an error.  So, we
no longer need to check data_size before running memdup_user because
checking the return value of the function is sufficient.

Signed-off-by: Jonathan Cavitt <jonathan.cav...@intel.com>
Cc: Andi Shyti <andi.sh...@linux.intel.com>
---
 drivers/gpu/drm/i915/gvt/kvmgt.c | 18 ++++++++++++------
 1 file changed, 12 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/i915/gvt/kvmgt.c b/drivers/gpu/drm/i915/gvt/kvmgt.c
index 69830a5c49d3..d1c9d43ae12f 100644
--- a/drivers/gpu/drm/i915/gvt/kvmgt.c
+++ b/drivers/gpu/drm/i915/gvt/kvmgt.c
@@ -1361,21 +1361,27 @@ static long intel_vgpu_ioctl(struct vfio_device 
*vfio_dev, unsigned int cmd,
                if (copy_from_user(&hdr, (void __user *)arg, minsz))
                        return -EFAULT;
 
+               if (hweight32(hdr.flags & VFIO_IRQ_DATA_TYPE_MASK) != 1 ||
+                   hweight32(hdr.flags & VFIO_IRQ_ACTION_TYPE_MASK) != 1)
+                       return -EINVAL;
+
                if (!(hdr.flags & VFIO_IRQ_SET_DATA_NONE)) {
                        int max = intel_vgpu_get_irq_count(vgpu, hdr.index);
 
+                       if (!hdr.count)
+                               return -EINVAL;
+
                        ret = vfio_set_irqs_validate_and_prepare(&hdr, max,
                                                VFIO_PCI_NUM_IRQS, &data_size);
                        if (ret) {
                                
gvt_vgpu_err("intel:vfio_set_irqs_validate_and_prepare failed\n");
                                return -EINVAL;
                        }
-                       if (data_size) {
-                               data = memdup_user((void __user *)(arg + minsz),
-                                                  data_size);
-                               if (IS_ERR(data))
-                                       return PTR_ERR(data);
-                       }
+
+                       data = memdup_user((void __user *)(arg + minsz),
+                                          data_size);
+                       if (IS_ERR(data))
+                               return PTR_ERR(data);
                }
 
                ret = intel_vgpu_set_irqs(vgpu, hdr.flags, hdr.index,
-- 
2.43.0

Reply via email to