From: Jacob Pan <jacob.pan@linux.microsoft.com>
To: Yuho Choi <oss.patchbox@gmail.com>
Cc: "Joerg Roedel (AMD)" <joro@8bytes.org>,
Will Deacon <will@kernel.org>, Wei Liu <wei.liu@kernel.org>,
Robin Murphy <robin.murphy@arm.com>,
Haiyang Zhang <haiyangz@microsoft.com>,
Dexuan Cui <decui@microsoft.com>,
Yu Zhang <zhangyu1@linux.microsoft.com>,
Easwar Hariharan <easwar.hariharan@linux.microsoft.com>,
Michael Kelley <mhklinux@outlook.com>,
Jason Gunthorpe <jgg@ziepe.ca>,
iommu@lists.linux.dev, linux-hyperv@vger.kernel.org,
linux-kernel@vger.kernel.org, jacob.pan@linux.microsoft.com
Subject: Re: [PATCH v1] iommu/hyperv: Don't free a paging domain the hypervisor did not delete
Date: Thu, 5 Nov 2026 14:14:27 -0800 [thread overview]
Message-ID: <20261105141427.00005946@linux.microsoft.com> (raw)
In-Reply-To: <20261105192738.70664-2-oss.patchbox@gmail.com>
Hi Yuho,
On Thu, 5 Nov 2026 14:27:08 -0500
Yuho Choi <oss.patchbox@gmail.com> wrote:
> hv_iommu_paging_domain_free() frees all page-table pages with
> pt_iommu_deinit() and only then asks the hypervisor to delete the
> device domain that points at them. If HVCALL_DELETE_DEVICE_DOMAIN
> fails, hv_delete_device_domain() only logs the error, returns the
> domain ID to the IDA, and the domain is freed anyway.
>
> The hypervisor then keeps a device domain whose page tables have been
> freed and can be reused for anything. The ID is also handed out again
> by the next paging domain allocation, while the hypervisor still has a
> domain with that ID.
>
> Delete the domain before freeing its page tables, and keep the ID, the
> page tables and the domain if the hypervisor fails to delete it.
>
> Fixes: 2690d4156b51 ("iommu/hyperv: Add para-virtualized IOMMU
> support for Hyper-V guest") Signed-off-by: Yuho Choi
> <oss.patchbox@gmail.com> ---
> Compile-tested only (x86_64 with HYPERV and HYPERV_PVIOMMU,
> W=1); I have no Hyper-V guest with the para-virtualized IOMMU to test
> it on.
>
> drivers/iommu/hyperv/hv-iommu-guest.c | 17 +++++++++++++----
> 1 file changed, 13 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/iommu/hyperv/hv-iommu-guest.c
> b/drivers/iommu/hyperv/hv-iommu-guest.c index
> 876a22f21f1e..205c642c8d40 100644 ---
> a/drivers/iommu/hyperv/hv-iommu-guest.c +++
> b/drivers/iommu/hyperv/hv-iommu-guest.c @@ -107,7 +107,7 @@ static
> int hv_create_device_domain(struct hv_iommu_domain *hv_domain) return
> hv_result_to_errno(status); }
>
> -static void hv_delete_device_domain(struct hv_iommu_domain
> *hv_domain) +static int hv_delete_device_domain(struct
> hv_iommu_domain *hv_domain) {
> u64 status;
> unsigned long flags;
> @@ -122,11 +122,15 @@ static void hv_delete_device_domain(struct
> hv_iommu_domain *hv_domain)
> local_irq_restore(flags);
>
> - if (!hv_result_success(status))
> + if (!hv_result_success(status)) {
> + /* The domain still exists, so its ID cannot be
> reused */ hv_status_err(status, "HVCALL_DELETE_DEVICE_DOMAIN
> failed\n");
> + return hv_result_to_errno(status);
> + }
>
> ida_free(&hv_domain->hv_iommu->domain_ids,
> hv_domain->device_domain.domain_id.id);
> + return 0;
> }
>
> static int
> @@ -466,11 +470,16 @@ static void hv_iommu_paging_domain_free(struct
> iommu_domain *domain) {
> struct hv_iommu_domain *hv_domain =
> to_hv_iommu_domain(domain);
> + /*
> + * If the hypervisor still has the domain, it may still use
> its page
> + * tables, so leak them.
> + */
> + if (hv_delete_device_domain(hv_domain))
> + return;
> +
> /* Free all remaining mappings */
> pt_iommu_deinit(&hv_domain->pt_iommu);
>
> - hv_delete_device_domain(hv_domain);
> -
> kfree(hv_domain);
> }
Looks good but I think it is incomplete.
if both hv_configure_device_domain and hv_delete_device_domain both
fails in hv_create_configure_device_domain, then unwind code will do
pt_iommu_deinit thus have the same UAF problem.
ret = hv_create_configure_device_domain(hv_domain, &settings);
if (ret)
goto err_pt_deinit;
return &hv_domain->domain;
err_pt_deinit:
pt_iommu_deinit(&hv_domain->pt_iommu);
hv_create_configure_device_domain(struct hv_iommu_domain
*hv_domain, const struct hv_device_domain_settings *settings)
{
int ret;
ret = hv_create_device_domain(hv_domain);
if (ret)
return ret;
ret = hv_configure_device_domain(hv_domain, settings);
if (ret)
hv_delete_device_domain(hv_domain);//fails here
return ret;
}
next prev parent reply other threads:[~2026-11-05 22:14 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-05 19:27 [PATCH v1] iommu/hyperv: Don't free a paging domain the hypervisor did not delete Yuho Choi
2026-11-05 19:53 ` Easwar Hariharan
2026-11-05 20:31 ` Jason Gunthorpe
2026-11-05 22:14 ` Jacob Pan [this message]
2026-11-06 4:30 ` Yuho Choi
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261105141427.00005946@linux.microsoft.com \
--to=jacob.pan@linux.microsoft.com \
--cc=decui@microsoft.com \
--cc=easwar.hariharan@linux.microsoft.com \
--cc=haiyangz@microsoft.com \
--cc=iommu@lists.linux.dev \
--cc=jgg@ziepe.ca \
--cc=joro@8bytes.org \
--cc=linux-hyperv@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=mhklinux@outlook.com \
--cc=oss.patchbox@gmail.com \
--cc=robin.murphy@arm.com \
--cc=wei.liu@kernel.org \
--cc=will@kernel.org \
--cc=zhangyu1@linux.microsoft.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.