diff options
author | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2014-02-02 20:22:07 -0500 |
---|---|---|
committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2014-02-03 16:28:02 -0500 |
commit | 2d7c1b77dd59387070aab355532dd157f888325c (patch) | |
tree | 7059fc37413f11ff25b87d78d6c068b8c0091734 | |
parent | 38dbfb59d1175ef458d006556061adeaa8751b72 (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.c | 8 |
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 && |