* [PATCH v1] iommu/hyperv: Don't free a paging domain the hypervisor did not delete
@ 2026-11-05 19:27 Yuho Choi
2026-11-05 19:53 ` Easwar Hariharan
` (2 more replies)
0 siblings, 3 replies; 5+ messages in thread
From: Yuho Choi @ 2026-11-05 19:27 UTC (permalink / raw)
To: Joerg Roedel (AMD), Will Deacon, Wei Liu
Cc: Robin Murphy, Haiyang Zhang, Dexuan Cui, Yu Zhang,
Easwar Hariharan, Jacob Pan, Michael Kelley, Jason Gunthorpe,
iommu, linux-hyperv, linux-kernel, Yuho Choi
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);
}
base-commit: 6628e7d4c6b25c8d18f1345e3a20d21829aae7e4
--
2.43.0
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH v1] iommu/hyperv: Don't free a paging domain the hypervisor did not delete
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
2 siblings, 0 replies; 5+ messages in thread
From: Easwar Hariharan @ 2026-11-05 19:53 UTC (permalink / raw)
To: Yuho Choi
Cc: Joerg Roedel (AMD), Will Deacon, Wei Liu, easwar.hariharan,
Robin Murphy, Haiyang Zhang, Dexuan Cui, Yu Zhang, Jacob Pan,
Michael Kelley, Jason Gunthorpe, iommu, linux-hyperv,
linux-kernel
On 11/5/2026 11:27, Yuho Choi 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(-)
>
Good catch!
Reviewed-by: Easwar Hariharan <easwar.hariharan@linux.microsoft.com>
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH v1] iommu/hyperv: Don't free a paging domain the hypervisor did not delete
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
2 siblings, 0 replies; 5+ messages in thread
From: Jason Gunthorpe @ 2026-11-05 20:31 UTC (permalink / raw)
To: Yuho Choi
Cc: Joerg Roedel (AMD), Will Deacon, Wei Liu, Robin Murphy,
Haiyang Zhang, Dexuan Cui, Yu Zhang, Easwar Hariharan, Jacob Pan,
Michael Kelley, iommu, linux-hyperv, linux-kernel
On Thu, Nov 05, 2026 at 02:27:08PM -0500, Yuho Choi 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.
Isn't there a WARN_ON on this path? I recall asking for one ..
So long as that is there this is the right way to continue
Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH v1] iommu/hyperv: Don't free a paging domain the hypervisor did not delete
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
2026-11-06 4:30 ` Yuho Choi
2 siblings, 1 reply; 5+ messages in thread
From: Jacob Pan @ 2026-11-05 22:14 UTC (permalink / raw)
To: Yuho Choi
Cc: Joerg Roedel (AMD), Will Deacon, Wei Liu, Robin Murphy,
Haiyang Zhang, Dexuan Cui, Yu Zhang, Easwar Hariharan,
Michael Kelley, Jason Gunthorpe, iommu, linux-hyperv,
linux-kernel, jacob.pan
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;
}
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH v1] iommu/hyperv: Don't free a paging domain the hypervisor did not delete
2026-11-05 22:14 ` Jacob Pan
@ 2026-11-06 4:30 ` Yuho Choi
0 siblings, 0 replies; 5+ messages in thread
From: Yuho Choi @ 2026-11-06 4:30 UTC (permalink / raw)
To: Jacob Pan, Jason Gunthorpe, Easwar Hariharan
Cc: Joerg Roedel (AMD), Will Deacon, Wei Liu, Robin Murphy,
Haiyang Zhang, Dexuan Cui, Yu Zhang, Michael Kelley, iommu,
linux-hyperv, linux-kernel
On Thu, Nov 05, 2026 at 02:27:08PM -0500, Yuho Choi 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.
>
> Isn't there a WARN_ON on this path? I recall asking for one ..
There isn't one yet. hv_delete_device_domain() only prints the error
with hv_status_err(). The driver does WARN when a flush fails or when
attaching to the blocking domain fails, but not when a delete fails.
I'll add a WARN for the delete failure in v2.
> Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
Thanks for the review!
> 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.
You're right, thanks for catching this. If the delete also fails
there, hv_iommu_domain_alloc_paging() still frees the page tables.
In v2, I'll make hv_iommu_domain_alloc_paging() call
hv_create_device_domain() and hv_configure_device_domain() itself, so
it can leak the page tables and the domain when the delete fails, the
same way hv_iommu_paging_domain_free() does.
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2026-11-06 4:30 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
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
2026-11-06 4:30 ` Yuho Choi
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.