Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 2d7c1b77 authored by Rafael J. Wysocki's avatar Rafael J. Wysocki
Browse files

ACPI / hotplug / PCI: Remove entries from bus->devices in reverse order



According to the changelog of commit 29ed1f29 (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: default avatarRafael J. Wysocki <rafael.j.wysocki@intel.com>
Tested-by: default avatarMika Westerberg <mika.westerberg@linux.intel.com>
parent 38dbfb59
Loading
Loading
Loading
Loading
+4 −4
Original line number Diff line number Diff line
@@ -742,7 +742,7 @@ static void trim_stale_devices(struct pci_dev *dev)

		/* The device is a bridge. so check the bus below it. */
		pm_runtime_get_sync(&dev->dev);
		list_for_each_entry_safe(child, tmp, &bus->devices, bus_list)
		list_for_each_entry_safe_reverse(child, tmp, &bus->devices, bus_list)
			trim_stale_devices(child);

		pm_runtime_put(&dev->dev);
@@ -773,8 +773,8 @@ static void acpiphp_check_bridge(struct acpiphp_bridge *bridge)
			; /* do nothing */
		} else if (get_slot_status(slot) == ACPI_STA_ALL) {
			/* remove stale devices if any */
			list_for_each_entry_safe(dev, tmp, &bus->devices,
						 bus_list)
			list_for_each_entry_safe_reverse(dev, tmp,
							 &bus->devices, bus_list)
				if (PCI_SLOT(dev->devfn) == slot->device)
					trim_stale_devices(dev);

@@ -805,7 +805,7 @@ static void acpiphp_sanitize_bus(struct pci_bus *bus)
	int i;
	unsigned long type_mask = IORESOURCE_IO | IORESOURCE_MEM;

	list_for_each_entry_safe(dev, tmp, &bus->devices, bus_list) {
	list_for_each_entry_safe_reverse(dev, tmp, &bus->devices, bus_list) {
		for (i=0; i<PCI_BRIDGE_RESOURCES; i++) {
			struct resource *res = &dev->resource[i];
			if ((res->flags & type_mask) && !res->start &&