Skip to content

Commit 8e22f68

Browse files
Jon Derrickgregkh
authored andcommitted
irqdomain/treewide: Free firmware node after domain removal
commit ec01608 upstream. Commit 711419e ("irqdomain: Add the missing assignment of domain->fwnode for named fwnode") unintentionally caused a dangling pointer page fault issue on firmware nodes that were freed after IRQ domain allocation. Commit e3beca4 fixed that dangling pointer issue by only freeing the firmware node after an IRQ domain allocation failure. That fix no longer frees the firmware node immediately, but leaves the firmware node allocated after the domain is removed. The firmware node must be kept around through irq_domain_remove, but should be freed it afterwards. Add the missing free operations after domain removal where where appropriate. Fixes: e3beca4 ("irqdomain/treewide: Keep firmware node unconditionally allocated") Signed-off-by: Jon Derrick <jonathan.derrick@intel.com> Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> Acked-by: Bjorn Helgaas <bhelgaas@google.com> # drivers/pci Cc: stable@vger.kernel.org Link: https://lkml.kernel.org/r/1595363169-7157-1-git-send-email-jonathan.derrick@intel.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent c0cfb9e commit 8e22f68

3 files changed

Lines changed: 16 additions & 0 deletions

File tree

arch/x86/kernel/apic/io_apic.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2342,8 +2342,13 @@ static int mp_irqdomain_create(int ioapic)
23422342

23432343
static void ioapic_destroy_irqdomain(int idx)
23442344
{
2345+
struct ioapic_domain_cfg *cfg = &ioapics[idx].irqdomain_cfg;
2346+
struct fwnode_handle *fn = ioapics[idx].irqdomain->fwnode;
2347+
23452348
if (ioapics[idx].irqdomain) {
23462349
irq_domain_remove(ioapics[idx].irqdomain);
2350+
if (!cfg->dev)
2351+
irq_domain_free_fwnode(fn);
23472352
ioapics[idx].irqdomain = NULL;
23482353
}
23492354
}

drivers/iommu/intel_irq_remapping.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -601,13 +601,21 @@ static int intel_setup_irq_remapping(struct intel_iommu *iommu)
601601

602602
static void intel_teardown_irq_remapping(struct intel_iommu *iommu)
603603
{
604+
struct fwnode_handle *fn;
605+
604606
if (iommu && iommu->ir_table) {
605607
if (iommu->ir_msi_domain) {
608+
fn = iommu->ir_msi_domain->fwnode;
609+
606610
irq_domain_remove(iommu->ir_msi_domain);
611+
irq_domain_free_fwnode(fn);
607612
iommu->ir_msi_domain = NULL;
608613
}
609614
if (iommu->ir_domain) {
615+
fn = iommu->ir_domain->fwnode;
616+
610617
irq_domain_remove(iommu->ir_domain);
618+
irq_domain_free_fwnode(fn);
611619
iommu->ir_domain = NULL;
612620
}
613621
free_pages((unsigned long)iommu->ir_table->base,

drivers/pci/controller/vmd.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -718,6 +718,7 @@ static int vmd_enable_domain(struct vmd_dev *vmd, unsigned long features)
718718
if (!vmd->bus) {
719719
pci_free_resource_list(&resources);
720720
irq_domain_remove(vmd->irq_domain);
721+
irq_domain_free_fwnode(fn);
721722
return -ENODEV;
722723
}
723724

@@ -820,6 +821,7 @@ static void vmd_cleanup_srcu(struct vmd_dev *vmd)
820821
static void vmd_remove(struct pci_dev *dev)
821822
{
822823
struct vmd_dev *vmd = pci_get_drvdata(dev);
824+
struct fwnode_handle *fn = vmd->irq_domain->fwnode;
823825

824826
sysfs_remove_link(&vmd->dev->dev.kobj, "domain");
825827
pci_stop_root_bus(vmd->bus);
@@ -828,6 +830,7 @@ static void vmd_remove(struct pci_dev *dev)
828830
vmd_teardown_dma_ops(vmd);
829831
vmd_detach_resources(vmd);
830832
irq_domain_remove(vmd->irq_domain);
833+
irq_domain_free_fwnode(fn);
831834
}
832835

833836
#ifdef CONFIG_PM_SLEEP

0 commit comments

Comments
 (0)