aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/hotplug/pciehp.h
diff options
context:
space:
mode:
authorLukas Wunner <lukas@wunner.de>2018-07-19 17:27:32 -0500
committerBjorn Helgaas <helgaas@kernel.org>2018-07-23 17:04:10 -0500
commit281e878eab191cce4259abbbf1a0322e3adae02c (patch)
treefe604441da8709a804ca979b4864caf8e33ed079 /drivers/pci/hotplug/pciehp.h
parentPCI: hotplug: Don't leak pci_slot on registration failure (diff)
downloadlinux-dev-281e878eab191cce4259abbbf1a0322e3adae02c.tar.xz
linux-dev-281e878eab191cce4259abbbf1a0322e3adae02c.zip
PCI: pciehp: Fix use-after-free on unplug
When pciehp is unbound (e.g. on unplug of a Thunderbolt device), the hotplug_slot struct is deregistered and thus freed before freeing the IRQ. The IRQ handler and the work items it schedules print the slot name referenced from the freed structure in various informational and debug log messages, each time resulting in a quadruple dereference of freed pointers (hotplug_slot -> pci_slot -> kobject -> name). At best the slot name is logged as "(null)", at worst kernel memory is exposed in logs or the driver crashes: pciehp 0000:10:00.0:pcie204: Slot((null)): Card not present An attacker may provoke the bug by unplugging multiple devices on a Thunderbolt daisy chain at once. Unplugging can also be simulated by powering down slots via sysfs. The bug is particularly easy to trigger in poll mode. It has been present since the driver's introduction in 2004: https://git.kernel.org/tglx/history/c/c16b4b14d980 Fix by rearranging teardown such that the IRQ is freed first. Run the work items queued by the IRQ handler to completion before freeing the hotplug_slot struct by draining the work queue from the ->release_slot callback which is invoked by pci_hp_deregister(). Signed-off-by: Lukas Wunner <lukas@wunner.de> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Cc: stable@vger.kernel.org # v2.6.4
Diffstat (limited to 'drivers/pci/hotplug/pciehp.h')
-rw-r--r--drivers/pci/hotplug/pciehp.h1
1 files changed, 1 insertions, 0 deletions
diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h
index 5f892065585e..fca87a1a2b22 100644
--- a/drivers/pci/hotplug/pciehp.h
+++ b/drivers/pci/hotplug/pciehp.h
@@ -119,6 +119,7 @@ int pciehp_unconfigure_device(struct slot *p_slot);
void pciehp_queue_pushbutton_work(struct work_struct *work);
struct controller *pcie_init(struct pcie_device *dev);
int pcie_init_notification(struct controller *ctrl);
+void pcie_shutdown_notification(struct controller *ctrl);
int pciehp_enable_slot(struct slot *p_slot);
int pciehp_disable_slot(struct slot *p_slot);
void pcie_reenable_notification(struct controller *ctrl);