iommu: Add iommu_copy_struct_from_user helper
authorNicolin Chen <nicolinc@nvidia.com>
Thu, 26 Oct 2023 04:39:36 +0000 (21:39 -0700)
committerJason Gunthorpe <jgg@nvidia.com>
Thu, 26 Oct 2023 14:15:57 +0000 (11:15 -0300)
Wrap up the data type/pointer/len sanity and a copy_struct_from_user call
for iommu drivers to copy driver specific data via struct iommu_user_data.
And expect it to be used in the domain_alloc_user op for example.

Link: https://lore.kernel.org/r/20231026043938.63898-9-yi.l.liu@intel.com
Signed-off-by: Nicolin Chen <nicolinc@nvidia.com>
Co-developed-by: Yi Liu <yi.l.liu@intel.com>
Signed-off-by: Yi Liu <yi.l.liu@intel.com>
Reviewed-by: Kevin Tian <kevin.tian@intel.com>
Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
include/linux/iommu.h

index 2ddd99f55471ba89fd2a0a605f48b4cdeda9cb61..8fb1b41b4d1580a4c5c3f45c4fb7fb557dca464d 100644 (file)
@@ -280,6 +280,46 @@ struct iommu_user_data {
        size_t len;
 };
 
+/**
+ * __iommu_copy_struct_from_user - Copy iommu driver specific user space data
+ * @dst_data: Pointer to an iommu driver specific user data that is defined in
+ *            include/uapi/linux/iommufd.h
+ * @src_data: Pointer to a struct iommu_user_data for user space data info
+ * @data_type: The data type of the @dst_data. Must match with @src_data.type
+ * @data_len: Length of current user data structure, i.e. sizeof(struct _dst)
+ * @min_len: Initial length of user data structure for backward compatibility.
+ *           This should be offsetofend using the last member in the user data
+ *           struct that was initially added to include/uapi/linux/iommufd.h
+ */
+static inline int __iommu_copy_struct_from_user(
+       void *dst_data, const struct iommu_user_data *src_data,
+       unsigned int data_type, size_t data_len, size_t min_len)
+{
+       if (src_data->type != data_type)
+               return -EINVAL;
+       if (WARN_ON(!dst_data || !src_data))
+               return -EINVAL;
+       if (src_data->len < min_len || data_len < src_data->len)
+               return -EINVAL;
+       return copy_struct_from_user(dst_data, data_len, src_data->uptr,
+                                    src_data->len);
+}
+
+/**
+ * iommu_copy_struct_from_user - Copy iommu driver specific user space data
+ * @kdst: Pointer to an iommu driver specific user data that is defined in
+ *        include/uapi/linux/iommufd.h
+ * @user_data: Pointer to a struct iommu_user_data for user space data info
+ * @data_type: The data type of the @kdst. Must match with @user_data->type
+ * @min_last: The last memember of the data structure @kdst points in the
+ *            initial version.
+ * Return 0 for success, otherwise -error.
+ */
+#define iommu_copy_struct_from_user(kdst, user_data, data_type, min_last) \
+       __iommu_copy_struct_from_user(kdst, user_data, data_type,         \
+                                     sizeof(*kdst),                      \
+                                     offsetofend(typeof(*kdst), min_last))
+
 /**
  * struct iommu_ops - iommu ops and capabilities
  * @capable: check capability