mirror of https://gitee.com/openkylin/linux.git
af9d8adc6b
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> |
||
---|---|---|
.. | ||
Kconfig | ||
Makefile | ||
acpi_pcihp.c | ||
acpiphp.h | ||
acpiphp_core.c | ||
acpiphp_glue.c | ||
acpiphp_ibm.c | ||
cpci_hotplug.h | ||
cpci_hotplug_core.c | ||
cpci_hotplug_pci.c | ||
cpcihp_generic.c | ||
cpcihp_zt5550.c | ||
cpcihp_zt5550.h | ||
cpqphp.h | ||
cpqphp_core.c | ||
cpqphp_ctrl.c | ||
cpqphp_nvram.c | ||
cpqphp_nvram.h | ||
cpqphp_pci.c | ||
cpqphp_sysfs.c | ||
ibmphp.h | ||
ibmphp_core.c | ||
ibmphp_ebda.c | ||
ibmphp_hpc.c | ||
ibmphp_pci.c | ||
ibmphp_res.c | ||
pci_hotplug_core.c | ||
pciehp.h | ||
pciehp_acpi.c | ||
pciehp_core.c | ||
pciehp_ctrl.c | ||
pciehp_hpc.c | ||
pciehp_pci.c | ||
pcihp_skeleton.c | ||
pcihp_slot.c | ||
rpadlpar.h | ||
rpadlpar_core.c | ||
rpadlpar_sysfs.c | ||
rpaphp.h | ||
rpaphp_core.c | ||
rpaphp_pci.c | ||
rpaphp_slot.c | ||
s390_pci_hpc.c | ||
sgi_hotplug.c | ||
shpchp.h | ||
shpchp_core.c | ||
shpchp_ctrl.c | ||
shpchp_hpc.c | ||
shpchp_pci.c | ||
shpchp_sysfs.c |