Commit 22a2f2e3 authored by Jonathan Cavitt's avatar Jonathan Cavitt Committed by Andi Shyti
Browse files

drm/i915/gvt: Improve intel_vgpu_ioctl hdr error handling



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.

v2: Use correct name for mask

v3: Use is_power_of_2 over hweight32 as it's more efficient (Andi)

Signed-off-by: default avatarJonathan Cavitt <jonathan.cavitt@intel.com>
Cc: Andi Shyti <andi.shyti@linux.intel.com>
Reviewed-by: default avatarZhenyu Wang <zhenyuw.linux@gmail.com>
Reviewed-by: default avatarKrzysztof Karas <krzysztof.karas@intel.com>
Reviewed-by: default avatarAndi Shyti <andi.shyti@linux.intel.com>
Signed-off-by: default avatarAndi Shyti <andi.shyti@linux.intel.com>
Link: https://lore.kernel.org/r/20250923212332.112137-2-jonathan.cavitt@intel.com
parent 69b4d367
Loading
Loading
Loading
Loading
+12 −6
Original line number Diff line number Diff line
@@ -1356,22 +1356,28 @@ 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 (!is_power_of_2(hdr.flags & VFIO_IRQ_SET_DATA_TYPE_MASK) ||
		    !is_power_of_2(hdr.flags & VFIO_IRQ_SET_ACTION_TYPE_MASK))
			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);
		}
		}

		ret = intel_vgpu_set_irqs(vgpu, hdr.flags, hdr.index,
					hdr.start, hdr.count, data);