
From: frankyj915 <yangjieyj.yang@huawei.com> vdpa inclusion category: bugfix CVE: NA -------------------------------- Error handling was missing when binding or attaching vDPA devices fails. And also iommufd_ctx should be put. Signed-off-by: frankyj915 <yangjieyj.yang@huawei.com> --- drivers/vhost/vdpa.c | 61 +++++++++++++++++++++++++++++++------------- 1 file changed, 43 insertions(+), 18 deletions(-) diff --git a/drivers/vhost/vdpa.c b/drivers/vhost/vdpa.c index 6d18e8cca2f0..7c5bbe26ae6e 100644 --- a/drivers/vhost/vdpa.c +++ b/drivers/vhost/vdpa.c @@ -581,7 +581,7 @@ static long vhost_vdpa_bind_iommufd(struct vhost_vdpa *v, int __user *argp) struct iommufd_device *idev; struct device *dma_dev = vdpa_get_dma_dev(v->vdpa); struct iommu_group *iommu_group = iommu_group_get(dma_dev); - int ret; + int ret = 0; if (copy_from_user(&bind, argp, sizeof(bind))) return -EFAULT; @@ -602,22 +602,48 @@ static long vhost_vdpa_bind_iommufd(struct vhost_vdpa *v, int __user *argp) dma_dev->bus->dma_cleanup(dma_dev); ret = iommu_group_claim_dma_owner(iommu_group, iommufd_ctx); if (ret) - return ret; + goto dma_configure; idev = iommufd_device_bind(iommufd_ctx, dma_dev, &bind.out_devid); - if (IS_ERR(idev)) - return PTR_ERR(idev); + if (IS_ERR(idev)) { + ret = PTR_ERR(idev); + goto release_owner; + } v->iommufd_dev = idev; - if (copy_to_user(argp, &bind, sizeof(bind))) - return -EFAULT; - return 0; + if (copy_to_user(argp, &bind, sizeof(bind))) { + ret = -EFAULT; + goto unbind; + } + + goto out; + +unbind: + iommufd_device_unbind(v->iommufd_dev); + v->iommufd_dev = NULL; +release_owner: + iommu_group_release_dma_owner(iommu_group); +dma_configure: + if (dma_dev->bus && dma_dev->bus->dma_configure) + dma_dev->bus->dma_configure(dma_dev); +out: + iommufd_ctx_put(iommufd_ctx); + return ret; +} + +static void vhost_vdpa_detach_iommufd_pt(struct vhost_vdpa *v) +{ + if (WARN_ON(!v->iommufd_dev) || !v->iommufd_attached) + return; + + iommufd_device_detach(v->iommufd_dev); + v->iommufd_attached = false; } static long vhost_vdpa_attach_iommufd_pt(struct vhost_vdpa *v, u32 __user *argp) { u32 pt_id = 0; - int ret; + int ret = 0; if (copy_from_user(&pt_id, argp, sizeof(pt_id))) return -EFAULT; @@ -627,18 +653,17 @@ static long vhost_vdpa_attach_iommufd_pt(struct vhost_vdpa *v, u32 __user *argp) return ret; v->iommufd_attached = true; - if (copy_to_user(argp, &pt_id, sizeof(pt_id))) - return -EFAULT; - return 0; -} + if (copy_to_user(argp, &pt_id, sizeof(pt_id))) { + ret = -EFAULT; + goto detach; + } -static void vhost_vdpa_detach_iommufd_pt(struct vhost_vdpa *v) -{ - if (WARN_ON(!v->iommufd_dev) || !v->iommufd_attached) - return; + goto out; - iommufd_device_detach(v->iommufd_dev); - v->iommufd_attached = false; +detach: + vhost_vdpa_detach_iommufd_pt(v); +out: + return ret; } static void vhost_vdpa_unbind_iommufd(struct vhost_vdpa *v) -- 2.25.1