On Fri, 16 Oct 2020 17:35:58 +0800 "xuxiaoyang (C)" <xuxiaoyang2@xxxxxxxxxx> wrote: > From 099744c26513e386e707faecb3f17726e236d9bc Mon Sep 17 00:00:00 2001 > From: Xiaoyang Xu <xuxiaoyang2@xxxxxxxxxx> > Date: Fri, 16 Oct 2020 15:32:02 +0800 > Subject: [PATCH] vfio iommu type1: Fix memory leak in > vfio_iommu_type1_pin_pages > > pfn is not added to pfn_list when vfio_add_to_pfn_list fails. > vfio_unpin_page_external will exit directly without calling > vfio_iova_put_vfio_pfn.This will lead to a memory leak. > > Signed-off-by: Xiaoyang Xu <xuxiaoyang2@xxxxxxxxxx> > --- > drivers/vfio/vfio_iommu_type1.c | 5 ++++- > 1 file changed, 4 insertions(+), 1 deletion(-) > > diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c > index c255a6683f31..26f518b02c81 100644 > --- a/drivers/vfio/vfio_iommu_type1.c > +++ b/drivers/vfio/vfio_iommu_type1.c > @@ -640,6 +640,7 @@ static int vfio_iommu_type1_pin_pages(void *iommu_data, > unsigned long remote_vaddr; > struct vfio_dma *dma; > bool do_accounting; > + int unlocked; > > if (!iommu || !user_pfn || !phys_pfn) > return -EINVAL; > @@ -693,7 +694,9 @@ static int vfio_iommu_type1_pin_pages(void *iommu_data, > > ret = vfio_add_to_pfn_list(dma, iova, phys_pfn[i]); > if (ret) { > - vfio_unpin_page_external(dma, iova, do_accounting); > + unlocked = put_pfn(phys_pfn[i], dma->prot); > + if (do_accounting) > + vfio_lock_acct(dma, -unlocked, true); > goto pin_unwind; > } > Thanks, this looks correct to me, but can also be simplified to: diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c index defd44522319..57b068abceb9 100644 --- a/drivers/vfio/vfio_iommu_type1.c +++ b/drivers/vfio/vfio_iommu_type1.c @@ -693,7 +693,8 @@ static int vfio_iommu_type1_pin_pages(void *iommu_data, ret = vfio_add_to_pfn_list(dma, iova, phys_pfn[i]); if (ret) { - vfio_unpin_page_external(dma, iova, do_accounting); + if (put_pfn(phys_pfn[i], dma->prot) && do_accounting) + vfio_lock_acct(dma, -1, true); goto pin_unwind; } ie. we don't need a variable to track the one page we unpin that might be accounted and we can avoid branching to vfio_lock_acct() for -0 unlocked. We should also add a Fixes tag so this propagates back to the relevant stable releases: Fixes: a54eb55045ae ("vfio iommu type1: Add support for mediated devices") I've made both of these changes in my next queue, please let me know if I've overlooked something or there's an objection. Thanks, Alex