linux/drivers/pci
Rafael J. Wysocki af9d8adc6b ACPI / hotplug / PCI: Fix bridge removal race vs dock events
If a PCI bridge with an ACPIPHP context attached is removed via
sysfs, the code path executed as a result is the following:

pci_stop_and_remove_bus_device_locked
 pci_remove_bus
  pcibios_remove_bus
   acpi_pci_remove_bus
    acpiphp_remove_slots
     cleanup_bridge
      unregister_hotplug_dock_device (drops dock references to the bridge)
     put_bridge
      free_bridge
       acpiphp_put_context (for each child, under context lock)
        kfree (context)

Now, if a dock event affecting one of the bridge's child devices
occurs (roughly at the same time), it will lead to the following code
path:

acpi_dock_deferred_cb
 dock_notify
  handle_eject_request
   hot_remove_dock_devices
    dock_hotplug_event
     hotplug_event (dereferences context)

That may lead to a kernel crash in hotplug_event() if it is executed
after the last kfree() in the bridge removal code path.

To prevent that from happening, add a wrapper around hotplug_event()
called dock_event() and point the .handler pointer in acpiphp_dock_ops
to it.  Make that wrapper retrieve the device's ACPIPHP context using
acpiphp_get_context() (instead of taking it from the data argument)
under acpiphp_context_lock and check if the parent bridge's
is_going_away flag is set.  If that flag is set, it will return
immediately and if it is not set it will grab a reference to the
device's parent bridge before executing hotplug_event().

Then, in the above scenario, the reference to the parent bridge
held by dock_event() will prevent free_bridge() from being executed
for it until hotplug_event() returns.

Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
2014-02-03 22:30:15 +01:00
..
host ARM: SoC cleanups for 3.14 2014-01-23 18:36:55 -08:00
hotplug ACPI / hotplug / PCI: Fix bridge removal race vs dock events 2014-02-03 22:30:15 +01:00
pcie Merge branch 'pci/dead-code' into next 2014-01-13 16:47:08 -07:00
access.c PCI: Remove unused pci_vpd_truncate() 2014-01-13 11:14:43 -07:00
ats.c PCI: Removed unused parts of Page Request Interface support 2014-01-10 14:00:47 -07:00
bus.c Merge branch 'pci/resource' into next 2014-01-10 14:23:15 -07:00
host-bridge.c PCI: Convert pcibios_resource_to_bus() to take a pci_bus, not a pci_dev 2013-12-21 10:06:10 -07:00
hotplug-pci.c
htirq.c
ioapic.c ACPI and power management updates for 3.14-rc1 2014-01-24 15:51:02 -08:00
iov.c PCI: Never treat a VF as a multifunction device 2014-01-10 10:05:26 -07:00
irq.c
Kconfig PCI: Convert ioapic to be builtin only, not modular 2014-01-03 14:31:38 -07:00
Makefile PCI: Add Virtual Channel to save/restore support 2013-12-17 17:39:08 -07:00
msi.c Merge branch 'pci/msi' into next 2014-01-07 17:34:39 -07:00
of.c
pci-acpi.c ACPI and power management updates for 3.14-rc1 2014-01-24 15:51:02 -08:00
pci-driver.c PCI: Disable Bus Master only on kexec reboot 2013-12-07 14:20:28 -07:00
pci-label.c ACPI and power management updates for 3.14-rc1 2014-01-24 15:51:02 -08:00
pci-stub.c
pci-sysfs.c PCI: Add global pci_lock_rescan_remove() 2014-01-13 17:49:49 -07:00
pci.c PCI changes for the v3.14 merge window: 2014-01-22 16:39:28 -08:00
pci.h PCI: Make local functions static 2014-01-13 11:57:29 -07:00
probe.c Revert "PCI: Remove from bus_list and release resources in pci_release_dev()" 2014-02-01 10:24:31 -08:00
proc.c
quirks.c PCI changes for the v3.14 merge window: 2014-01-22 16:39:28 -08:00
remove.c Revert "PCI: Remove from bus_list and release resources in pci_release_dev()" 2014-02-01 10:24:31 -08:00
rom.c PCI: Convert pcibios_resource_to_bus() to take a pci_bus, not a pci_dev 2013-12-21 10:06:10 -07:00
search.c
setup-bus.c Merge branch 'pci/resource' into next 2014-01-10 14:23:15 -07:00
setup-irq.c
setup-res.c PCI: Convert pcibios_resource_to_bus() to take a pci_bus, not a pci_dev 2013-12-21 10:06:10 -07:00
slot.c PCI: Remove unused pci_renumber_slot() 2014-01-13 11:14:44 -07:00
syscall.c
vc.c PCI: Rename PCI_VC_PORT_REG1/2 to PCI_VC_PORT_CAP1/2 2013-12-17 17:49:39 -07:00
vpd.c
xen-pcifront.c Features: 2014-01-22 22:00:18 -08:00