On Fri, Oct 25, 2024 at 04:49:44PM -0700, Nicolin Chen wrote:
> +void iommufd_viommu_destroy(struct iommufd_object *obj)
> +{
> +     struct iommufd_viommu *viommu =
> +             container_of(obj, struct iommufd_viommu, obj);
> +
> +     if (viommu->ops && viommu->ops->free)
> +             viommu->ops->free(viommu);

Ops can't be null and free can't be null, that would mean there is a
memory leak.

> +     refcount_dec(&viommu->hwpt->common.obj.users);

Don't touch viommu after freeing it

Did you run selftests with kasn?

> +int iommufd_viommu_alloc_ioctl(struct iommufd_ucmd *ucmd)
> +{
> +     struct iommu_viommu_alloc *cmd = ucmd->cmd;
> +     struct iommufd_hwpt_paging *hwpt_paging;
> +     struct iommufd_viommu *viommu;
> +     struct iommufd_device *idev;
> +     const struct iommu_ops *ops;
> +     int rc;
> +
> +     if (cmd->flags || cmd->type == IOMMU_VIOMMU_TYPE_DEFAULT)
> +             return -EOPNOTSUPP;
> +
> +     idev = iommufd_get_device(ucmd, cmd->dev_id);
> +     if (IS_ERR(idev))
> +             return PTR_ERR(idev);
> +
> +     ops = dev_iommu_ops(idev->dev);
> +     if (!ops->viommu_alloc) {
> +             rc = -EOPNOTSUPP;
> +             goto out_put_idev;
> +     }
> +
> +     hwpt_paging = iommufd_get_hwpt_paging(ucmd, cmd->hwpt_id);
> +     if (IS_ERR(hwpt_paging)) {
> +             rc = PTR_ERR(hwpt_paging);
> +             goto out_put_idev;
> +     }
> +
> +     if (!hwpt_paging->nest_parent) {
> +             rc = -EINVAL;
> +             goto out_put_hwpt;
> +     }
> +
> +     viommu = ops->viommu_alloc(idev->dev, hwpt_paging->common.domain,
> +                                ucmd->ictx, cmd->type);
> +     if (IS_ERR(viommu)) {
> +             rc = PTR_ERR(viommu);
> +             goto out_put_hwpt;
> +     }

Check that ops and ops->free are valid here with a WARN_ON

> +     rc = iommufd_verify_unfinalized_object(ucmd->ictx, &viommu->obj);
> +     if (rc) {
> +             kfree(viommu);
> +             goto out_put_hwpt;
> +     }
> +
> +     viommu->type = cmd->type;
> +     viommu->ictx = ucmd->ictx;
> +     viommu->hwpt = hwpt_paging;
> +     /*
> +      * It is the most likely case that a physical IOMMU is unpluggable. A
> +      * pluggable IOMMU instance (if exists) is responsible for refcounting
> +      * on its own.
> +      */
> +     viommu->iommu_dev = __iommu_get_iommu_dev(idev->dev);
> +
> +     refcount_inc(&viommu->hwpt->common.obj.users);

Put this line right after the one storing to viommu_>hwpt

Jason

Reply via email to