Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9df7b25a authored by Jiang Liu's avatar Jiang Liu Committed by Alex Williamson
Browse files

VFIO: unregister IOMMU notifier on error recovery path



On error recovery path in function vfio_create_group(), it should
unregister the IOMMU notifier for the new VFIO group. Otherwise it may
cause invalid memory access later when handling bus notifications.

Signed-off-by: default avatarJiang Liu <jiang.liu@huawei.com>
Signed-off-by: default avatarAlex Williamson <alex.williamson@redhat.com>
parent 2007722a
Loading
Loading
Loading
Loading
+15 −16
Original line number Diff line number Diff line
@@ -191,6 +191,17 @@ static void vfio_container_put(struct vfio_container *container)
	kref_put(&container->kref, vfio_container_release);
}

static void vfio_group_unlock_and_free(struct vfio_group *group)
{
	mutex_unlock(&vfio.group_lock);
	/*
	 * Unregister outside of lock.  A spurious callback is harmless now
	 * that the group is no longer in vfio.group_list.
	 */
	iommu_group_unregister_notifier(group->iommu_group, &group->nb);
	kfree(group);
}

/**
 * Group objects - create, release, get, put, search
 */
@@ -229,8 +240,7 @@ static struct vfio_group *vfio_create_group(struct iommu_group *iommu_group)

	minor = vfio_alloc_group_minor(group);
	if (minor < 0) {
		mutex_unlock(&vfio.group_lock);
		kfree(group);
		vfio_group_unlock_and_free(group);
		return ERR_PTR(minor);
	}

@@ -239,8 +249,7 @@ static struct vfio_group *vfio_create_group(struct iommu_group *iommu_group)
		if (tmp->iommu_group == iommu_group) {
			vfio_group_get(tmp);
			vfio_free_group_minor(minor);
			mutex_unlock(&vfio.group_lock);
			kfree(group);
			vfio_group_unlock_and_free(group);
			return tmp;
		}
	}
@@ -249,8 +258,7 @@ static struct vfio_group *vfio_create_group(struct iommu_group *iommu_group)
			    group, "%d", iommu_group_id(iommu_group));
	if (IS_ERR(dev)) {
		vfio_free_group_minor(minor);
		mutex_unlock(&vfio.group_lock);
		kfree(group);
		vfio_group_unlock_and_free(group);
		return (struct vfio_group *)dev; /* ERR_PTR */
	}

@@ -274,16 +282,7 @@ static void vfio_group_release(struct kref *kref)
	device_destroy(vfio.class, MKDEV(MAJOR(vfio.devt), group->minor));
	list_del(&group->vfio_next);
	vfio_free_group_minor(group->minor);

	mutex_unlock(&vfio.group_lock);

	/*
	 * Unregister outside of lock.  A spurious callback is harmless now
	 * that the group is no longer in vfio.group_list.
	 */
	iommu_group_unregister_notifier(group->iommu_group, &group->nb);

	kfree(group);
	vfio_group_unlock_and_free(group);
}

static void vfio_group_put(struct vfio_group *group)