Skip to content

Commit b5b7417

Browse files
l1kgregkh
authored andcommitted
PCI: pciehp: Fix unprotected list iteration in IRQ handler
commit 1204e35 upstream. Commit b440bde ("PCI: Add pci_ignore_hotplug() to ignore hotplug events for a device") iterates over the devices on a hotplug port's subordinate bus in pciehp's IRQ handler without acquiring pci_bus_sem. It is thus possible for a user to cause a crash by concurrently manipulating the device list, e.g. by disabling slot power via sysfs on a different CPU or by initiating a remove/rescan via sysfs. This can't be fixed by acquiring pci_bus_sem because it may sleep. The simplest fix is to avoid the list iteration altogether and just check the ignore_hotplug flag on the port itself. This works because pci_ignore_hotplug() sets the flag both on the device as well as on its parent bridge. We do lose the ability to print the name of the device blocking hotplug in the debug message, but that's probably bearable. Fixes: b440bde ("PCI: Add pci_ignore_hotplug() to ignore hotplug events for a device") Signed-off-by: Lukas Wunner <lukas@wunner.de> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Cc: stable@vger.kernel.org Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 2f27dfa commit b5b7417

1 file changed

Lines changed: 3 additions & 10 deletions

File tree

drivers/pci/hotplug/pciehp_hpc.c

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -562,8 +562,6 @@ static irqreturn_t pciehp_isr(int irq, void *dev_id)
562562
{
563563
struct controller *ctrl = (struct controller *)dev_id;
564564
struct pci_dev *pdev = ctrl_dev(ctrl);
565-
struct pci_bus *subordinate = pdev->subordinate;
566-
struct pci_dev *dev;
567565
struct slot *slot = ctrl->slot;
568566
u16 status, events;
569567
u8 present;
@@ -611,14 +609,9 @@ static irqreturn_t pciehp_isr(int irq, void *dev_id)
611609
wake_up(&ctrl->queue);
612610
}
613611

614-
if (subordinate) {
615-
list_for_each_entry(dev, &subordinate->devices, bus_list) {
616-
if (dev->ignore_hotplug) {
617-
ctrl_dbg(ctrl, "ignoring hotplug event %#06x (%s requested no hotplug)\n",
618-
events, pci_name(dev));
619-
return IRQ_HANDLED;
620-
}
621-
}
612+
if (pdev->ignore_hotplug) {
613+
ctrl_dbg(ctrl, "ignoring hotplug event %#06x\n", events);
614+
return IRQ_HANDLED;
622615
}
623616

624617
/* Check Attention Button Pressed */

0 commit comments

Comments
 (0)