]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
PCI/MSI: Destroy sysfs before freeing entries
authorThomas Gleixner <tglx@linutronix.de>
Tue, 9 Nov 2021 13:53:57 +0000 (14:53 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 21 Nov 2021 12:49:08 +0000 (13:49 +0100)
commit 3735459037114d31e5acd9894fad9aed104231a0 upstream.

free_msi_irqs() frees the MSI entries before destroying the sysfs entries
which are exposing them. Nothing prevents a concurrent free while a sysfs
file is read and accesses the possibly freed entry.

Move the sysfs release ahead of freeing the entries.

Fixes: 1c51b50c2995 ("PCI/MSI: Export MSI mode using attributes, not kobjects")
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Bjorn Helgaas <helgaas@kernel.org>
Cc: stable@vger.kernel.org
Link: https://lore.kernel.org/r/87sfw5305m.ffs@tglx
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/pci/msi.c

index 3a9f4f8ad8f94005d568602a924128d4c1bd298d..30bec2482e2733ffb0eb378e1284897f1ea3a20a 100644 (file)
@@ -368,18 +368,6 @@ static void free_msi_irqs(struct pci_dev *dev)
                        for (i = 0; i < entry->nvec_used; i++)
                                BUG_ON(irq_has_action(entry->irq + i));
 
-       pci_msi_teardown_msi_irqs(dev);
-
-       list_for_each_entry_safe(entry, tmp, msi_list, list) {
-               if (entry->msi_attrib.is_msix) {
-                       if (list_is_last(&entry->list, msi_list))
-                               iounmap(entry->mask_base);
-               }
-
-               list_del(&entry->list);
-               free_msi_entry(entry);
-       }
-
        if (dev->msi_irq_groups) {
                sysfs_remove_groups(&dev->dev.kobj, dev->msi_irq_groups);
                msi_attrs = dev->msi_irq_groups[0]->attrs;
@@ -395,6 +383,18 @@ static void free_msi_irqs(struct pci_dev *dev)
                kfree(dev->msi_irq_groups);
                dev->msi_irq_groups = NULL;
        }
+
+       pci_msi_teardown_msi_irqs(dev);
+
+       list_for_each_entry_safe(entry, tmp, msi_list, list) {
+               if (entry->msi_attrib.is_msix) {
+                       if (list_is_last(&entry->list, msi_list))
+                               iounmap(entry->mask_base);
+               }
+
+               list_del(&entry->list);
+               free_msi_entry(entry);
+       }
 }
 
 static void pci_intx_for_msi(struct pci_dev *dev, int enable)