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