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: Jiang Liu <jiang.liu@huawei.com> Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
This commit is contained in:
parent
2007722a60
commit
9df7b25ab7
|
@ -191,6 +191,17 @@ static void vfio_container_put(struct vfio_container *container)
|
||||||
kref_put(&container->kref, vfio_container_release);
|
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
|
* 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);
|
minor = vfio_alloc_group_minor(group);
|
||||||
if (minor < 0) {
|
if (minor < 0) {
|
||||||
mutex_unlock(&vfio.group_lock);
|
vfio_group_unlock_and_free(group);
|
||||||
kfree(group);
|
|
||||||
return ERR_PTR(minor);
|
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) {
|
if (tmp->iommu_group == iommu_group) {
|
||||||
vfio_group_get(tmp);
|
vfio_group_get(tmp);
|
||||||
vfio_free_group_minor(minor);
|
vfio_free_group_minor(minor);
|
||||||
mutex_unlock(&vfio.group_lock);
|
vfio_group_unlock_and_free(group);
|
||||||
kfree(group);
|
|
||||||
return tmp;
|
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));
|
group, "%d", iommu_group_id(iommu_group));
|
||||||
if (IS_ERR(dev)) {
|
if (IS_ERR(dev)) {
|
||||||
vfio_free_group_minor(minor);
|
vfio_free_group_minor(minor);
|
||||||
mutex_unlock(&vfio.group_lock);
|
vfio_group_unlock_and_free(group);
|
||||||
kfree(group);
|
|
||||||
return (struct vfio_group *)dev; /* ERR_PTR */
|
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));
|
device_destroy(vfio.class, MKDEV(MAJOR(vfio.devt), group->minor));
|
||||||
list_del(&group->vfio_next);
|
list_del(&group->vfio_next);
|
||||||
vfio_free_group_minor(group->minor);
|
vfio_free_group_minor(group->minor);
|
||||||
|
vfio_group_unlock_and_free(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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void vfio_group_put(struct vfio_group *group)
|
static void vfio_group_put(struct vfio_group *group)
|
||||||
|
|
Loading…
Reference in New Issue