struct hisi_acc_vf_core_device *hisi_acc_vdev = migf->hisi_acc_vdev;
loff_t *pos = &filp->f_pos;
struct vfio_precopy_info info;
- unsigned long minsz;
int ret;
- if (cmd != VFIO_MIG_GET_PRECOPY_INFO)
- return -ENOTTY;
-
- minsz = offsetofend(struct vfio_precopy_info, dirty_bytes);
-
- if (copy_from_user(&info, (void __user *)arg, minsz))
- return -EFAULT;
- if (info.argsz < minsz)
- return -EINVAL;
+ ret = vfio_check_precopy_ioctl(&hisi_acc_vdev->core_device.vdev, cmd,
+ arg, &info);
+ if (ret)
+ return ret;
mutex_lock(&hisi_acc_vdev->state_mutex);
if (hisi_acc_vdev->mig_state != VFIO_DEVICE_STATE_PRE_COPY) {
mutex_unlock(&migf->lock);
mutex_unlock(&hisi_acc_vdev->state_mutex);
- return copy_to_user((void __user *)arg, &info, minsz) ? -EFAULT : 0;
+ return copy_to_user((void __user *)arg, &info,
+ offsetofend(struct vfio_precopy_info, dirty_bytes)) ? -EFAULT : 0;
out:
mutex_unlock(&migf->lock);
mutex_unlock(&hisi_acc_vdev->state_mutex);
struct mlx5_vhca_data_buffer *buf;
struct vfio_precopy_info info = {};
loff_t *pos = &filp->f_pos;
- unsigned long minsz;
size_t inc_length = 0;
bool end_of_data = false;
int ret;
- if (cmd != VFIO_MIG_GET_PRECOPY_INFO)
- return -ENOTTY;
-
- minsz = offsetofend(struct vfio_precopy_info, dirty_bytes);
-
- if (copy_from_user(&info, (void __user *)arg, minsz))
- return -EFAULT;
-
- if (info.argsz < minsz)
- return -EINVAL;
+ ret = vfio_check_precopy_ioctl(&mvdev->core_device.vdev, cmd, arg,
+ &info);
+ if (ret)
+ return ret;
mutex_lock(&mvdev->state_mutex);
if (mvdev->mig_state != VFIO_DEVICE_STATE_PRE_COPY &&
done:
mlx5vf_state_mutex_unlock(mvdev);
- if (copy_to_user((void __user *)arg, &info, minsz))
+ if (copy_to_user((void __user *)arg, &info,
+ offsetofend(struct vfio_precopy_info, dirty_bytes)))
return -EFAULT;
return 0;
struct qat_mig_dev *mig_dev = qat_vdev->mdev;
struct vfio_precopy_info info;
loff_t *pos = &filp->f_pos;
- unsigned long minsz;
int ret = 0;
- if (cmd != VFIO_MIG_GET_PRECOPY_INFO)
- return -ENOTTY;
-
- minsz = offsetofend(struct vfio_precopy_info, dirty_bytes);
-
- if (copy_from_user(&info, (void __user *)arg, minsz))
- return -EFAULT;
- if (info.argsz < minsz)
- return -EINVAL;
+ ret = vfio_check_precopy_ioctl(&qat_vdev->core_device.vdev, cmd, arg,
+ &info);
+ if (ret)
+ return ret;
mutex_lock(&qat_vdev->state_mutex);
if (qat_vdev->mig_state != VFIO_DEVICE_STATE_PRE_COPY &&
mutex_unlock(&qat_vdev->state_mutex);
if (ret)
return ret;
- return copy_to_user((void __user *)arg, &info, minsz) ? -EFAULT : 0;
+ return copy_to_user((void __user *)arg, &info,
+ offsetofend(struct vfio_precopy_info, dirty_bytes)) ? -EFAULT : 0;
}
static ssize_t qat_vf_save_read(struct file *filp, char __user *buf,
struct vfio_precopy_info info = {};
loff_t *pos = &filp->f_pos;
bool end_of_data = false;
- unsigned long minsz;
u32 ctx_size = 0;
int ret;
- if (cmd != VFIO_MIG_GET_PRECOPY_INFO)
- return -ENOTTY;
-
- minsz = offsetofend(struct vfio_precopy_info, dirty_bytes);
- if (copy_from_user(&info, (void __user *)arg, minsz))
- return -EFAULT;
-
- if (info.argsz < minsz)
- return -EINVAL;
+ ret = vfio_check_precopy_ioctl(&virtvdev->core_device.vdev, cmd, arg,
+ &info);
+ if (ret)
+ return ret;
mutex_lock(&virtvdev->state_mutex);
if (virtvdev->mig_state != VFIO_DEVICE_STATE_PRE_COPY &&
done:
virtiovf_state_mutex_unlock(virtvdev);
- if (copy_to_user((void __user *)arg, &info, minsz))
+ if (copy_to_user((void __user *)arg, &info,
+ offsetofend(struct vfio_precopy_info, dirty_bytes)))
return -EFAULT;
return 0;
#include <linux/cdev.h>
#include <uapi/linux/vfio.h>
#include <linux/iova_bitmap.h>
+#include <linux/uaccess.h>
struct kvm;
struct iommufd_ctx;
return 1;
}
+/**
+ * vfio_check_precopy_ioctl - Validate user input for the VFIO_MIG_GET_PRECOPY_INFO ioctl
+ * @vdev: The vfio device
+ * @cmd: Cmd from the ioctl
+ * @arg: Arg from the ioctl
+ * @info: Driver pointer to hold the userspace input to the ioctl
+ *
+ * For use in a driver's get_precopy_info. Checks that the inputs to the
+ * VFIO_MIG_GET_PRECOPY_INFO ioctl are correct.
+
+ * Returns 0 on success, otherwise errno.
+ */
+
+static inline int
+vfio_check_precopy_ioctl(struct vfio_device *vdev, unsigned int cmd,
+ unsigned long arg, struct vfio_precopy_info *info)
+{
+ unsigned long minsz;
+
+ if (cmd != VFIO_MIG_GET_PRECOPY_INFO)
+ return -ENOTTY;
+
+ minsz = offsetofend(struct vfio_precopy_info, dirty_bytes);
+
+ if (copy_from_user(info, (void __user *)arg, minsz))
+ return -EFAULT;
+
+ if (info->argsz < minsz)
+ return -EINVAL;
+
+ /* keep v1 behaviour as is for compatibility reasons */
+ if (vdev->precopy_info_v2)
+ /* flags are output, set its initial value to 0 */
+ info->flags = 0;
+
+ return 0;
+}
+
struct vfio_device *_vfio_alloc_device(size_t size, struct device *dev,
const struct vfio_device_ops *ops);
#define vfio_alloc_device(dev_struct, member, dev, ops) \
struct mdev_state *mdev_state = migf->mdev_state;
loff_t *pos = &filp->f_pos;
struct vfio_precopy_info info = {};
- unsigned long minsz;
int ret;
- if (cmd != VFIO_MIG_GET_PRECOPY_INFO)
- return -ENOTTY;
-
- minsz = offsetofend(struct vfio_precopy_info, dirty_bytes);
-
- if (copy_from_user(&info, (void __user *)arg, minsz))
- return -EFAULT;
- if (info.argsz < minsz)
- return -EINVAL;
+ ret = vfio_check_precopy_ioctl(&mdev_state->vdev, cmd, arg, &info);
+ if (ret)
+ return ret;
mutex_lock(&mdev_state->state_mutex);
if (mdev_state->state != VFIO_DEVICE_STATE_PRE_COPY &&
info.initial_bytes = migf->filled_size - *pos;
mutex_unlock(&migf->lock);
- ret = copy_to_user((void __user *)arg, &info, minsz) ? -EFAULT : 0;
+ ret = copy_to_user((void __user *)arg, &info,
+ offsetofend(struct vfio_precopy_info, dirty_bytes)) ? -EFAULT : 0;
unlock:
mtty_state_mutex_unlock(mdev_state);
return ret;