aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>2014-02-02 20:22:07 -0500
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2014-02-03 16:28:02 -0500
commit2d7c1b77dd59387070aab355532dd157f888325c (patch)
tree7059fc37413f11ff25b87d78d6c068b8c0091734
parent38dbfb59d1175ef458d006556061adeaa8751b72 (diff)
ACPI / hotplug / PCI: Remove entries from bus->devices in reverse order
According to the changelog of commit 29ed1f29b68a (PCI: pciehp: Fix null pointer deref when hot-removing SR-IOV device) it is unsafe to walk the bus->devices list of a PCI bus and remove devices from it in direct order, because that may lead to NULL pointer dereferences related to virtual functions. For this reason, change all of the bus->devices list walks in acpiphp_glue.c during which devices may be removed to be carried out in reverse order. Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Tested-by: Mika Westerberg <mika.westerberg@linux.intel.com>
-rw-r--r--drivers/pci/hotplug/acpiphp_glue.c8
1 files changed, 4 insertions, 4 deletions
diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c
index cd929aed3613..6a4b4b734fbd 100644
--- a/drivers/pci/hotplug/acpiphp_glue.c
+++ b/drivers/pci/hotplug/acpiphp_glue.c
@@ -742,7 +742,7 @@ static void trim_stale_devices(struct pci_dev *dev)
742 742
743 /* The device is a bridge. so check the bus below it. */ 743 /* The device is a bridge. so check the bus below it. */
744 pm_runtime_get_sync(&dev->dev); 744 pm_runtime_get_sync(&dev->dev);
745 list_for_each_entry_safe(child, tmp, &bus->devices, bus_list) 745 list_for_each_entry_safe_reverse(child, tmp, &bus->devices, bus_list)
746 trim_stale_devices(child); 746 trim_stale_devices(child);
747 747
748 pm_runtime_put(&dev->dev); 748 pm_runtime_put(&dev->dev);
@@ -773,8 +773,8 @@ static void acpiphp_check_bridge(struct acpiphp_bridge *bridge)
773 ; /* do nothing */ 773 ; /* do nothing */
774 } else if (get_slot_status(slot) == ACPI_STA_ALL) { 774 } else if (get_slot_status(slot) == ACPI_STA_ALL) {
775 /* remove stale devices if any */ 775 /* remove stale devices if any */
776 list_for_each_entry_safe(dev, tmp, &bus->devices, 776 list_for_each_entry_safe_reverse(dev, tmp,
777 bus_list) 777 &bus->devices, bus_list)
778 if (PCI_SLOT(dev->devfn) == slot->device) 778 if (PCI_SLOT(dev->devfn) == slot->device)
779 trim_stale_devices(dev); 779 trim_stale_devices(dev);
780 780
@@ -805,7 +805,7 @@ static void acpiphp_sanitize_bus(struct pci_bus *bus)
805 int i; 805 int i;
806 unsigned long type_mask = IORESOURCE_IO | IORESOURCE_MEM; 806 unsigned long type_mask = IORESOURCE_IO | IORESOURCE_MEM;
807 807
808 list_for_each_entry_safe(dev, tmp, &bus->devices, bus_list) { 808 list_for_each_entry_safe_reverse(dev, tmp, &bus->devices, bus_list) {
809 for (i=0; i<PCI_BRIDGE_RESOURCES; i++) { 809 for (i=0; i<PCI_BRIDGE_RESOURCES; i++) {
810 struct resource *res = &dev->resource[i]; 810 struct resource *res = &dev->resource[i];
811 if ((res->flags & type_mask) && !res->start && 811 if ((res->flags & type_mask) && !res->start &&