git: 27029bc08f1d - main - vmm: fix use after free in ppt_detach()

From: Robert Wing <rew_at_FreeBSD.org>
Date: Fri, 20 Jan 2023 20:25:32 UTC
The branch main has been updated by rew:

URL: https://cgit.FreeBSD.org/src/commit/?id=27029bc08f1d7fdb39b2aee6ff8263f68dd93495

commit 27029bc08f1d7fdb39b2aee6ff8263f68dd93495
Author:     Robert Wing <rew@FreeBSD.org>
AuthorDate: 2023-01-20 11:25:27 +0000
Commit:     Robert Wing <rew@FreeBSD.org>
CommitDate: 2023-01-20 11:25:27 +0000

    vmm: fix use after free in ppt_detach()
    
    The vmm module destroys the host_domain before unloading the ppt module
    causing a use after free. This can happen when kldunload'ing vmm.
    
    Reviewed by:    markj, jhb
    Differential Revision:  https://reviews.freebsd.org/D38072
---
 sys/amd64/vmm/intel/vtd.c | 2 ++
 sys/amd64/vmm/io/iommu.c  | 1 +
 sys/amd64/vmm/io/ppt.c    | 4 +++-
 3 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/sys/amd64/vmm/intel/vtd.c b/sys/amd64/vmm/intel/vtd.c
index 8f06dc823364..21e81223f6ee 100644
--- a/sys/amd64/vmm/intel/vtd.c
+++ b/sys/amd64/vmm/intel/vtd.c
@@ -446,6 +446,8 @@ vtd_add_device(void *arg, uint16_t rid)
 	struct vtdmap *vtdmap;
 	uint8_t bus;
 
+	KASSERT(dom != NULL, ("domain is NULL"));
+
 	bus = PCI_RID2BUS(rid);
 	ctxp = ctx_tables[bus];
 	pt_paddr = vtophys(dom->ptp);
diff --git a/sys/amd64/vmm/io/iommu.c b/sys/amd64/vmm/io/iommu.c
index 6a589f153815..01ce29539ec2 100644
--- a/sys/amd64/vmm/io/iommu.c
+++ b/sys/amd64/vmm/io/iommu.c
@@ -258,6 +258,7 @@ iommu_cleanup(void)
 	}
 	IOMMU_DISABLE();
 	IOMMU_DESTROY_DOMAIN(host_domain);
+	host_domain = NULL;
 	IOMMU_CLEANUP();
 }
 
diff --git a/sys/amd64/vmm/io/ppt.c b/sys/amd64/vmm/io/ppt.c
index edb65a3ac07b..26dad1832b10 100644
--- a/sys/amd64/vmm/io/ppt.c
+++ b/sys/amd64/vmm/io/ppt.c
@@ -182,7 +182,9 @@ ppt_detach(device_t dev)
 	num_pptdevs--;
 	TAILQ_REMOVE(&pptdev_list, ppt, next);
 	pci_disable_busmaster(dev);
-	iommu_add_device(iommu_host_domain(), pci_get_rid(dev));
+
+	if (iommu_host_domain() != NULL)
+		iommu_add_device(iommu_host_domain(), pci_get_rid(dev));
 
 	return (0);
 }