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