• Yinghai Lu's avatar
    PCI/ASPM: Always set link->downstream to avoid NULL dereference on remove · 3bd7db63
    Yinghai Lu authored
    We call pcie_aspm_exit_link_state() when we remove a device.  If the device
    is the last PCIe function to be removed below a bridge and the bridge has
    an ASPM link_state struct, we disable ASPM on the link.  Disabling ASPM
    requires link->downstream (used in pcie_config_aspm_link()).
    
    We previously set link->downstream in pcie_aspm_cap_init(), but only if the
    device was not blacklisted.  Removing the blacklisted device caused a NULL
    pointer dereference in the pcie_aspm_exit_link_state() ->
    pcie_config_aspm_link() path:
    
      # echo 1 > /sys/bus/pci/devices/0000\:0b\:00.0/remove
      ...
       BUG: unable to handle kernel NULL pointer dereference at 0000000000000080
       IP: pcie_config_aspm_link+0x5d/0x2b0
       Call Trace:
        pcie_aspm_exit_link_state+0x75/0x130
        pci_stop_bus_device+0xa4/0xb0
        pci_stop_and_remove_bus_device_locked+0x1a/0x30
        remove_store+0x50/0x70
        dev_attr_store+0x18/0x30
        sysfs_kf_write+0x44/0x60
        kernfs_fop_write+0x10e/0x190
        __vfs_write+0x28/0x110
        ? rcu_read_lock_sched_held+0x5d/0x80
        ? rcu_sync_lockdep_assert+0x2c/0x60
        ? __sb_start_write+0x173/0x1a0
        ? vfs_write+0xb3/0x180
        vfs_write+0xc4/0x180
        SyS_write+0x49/0xa0
        do_syscall_64+0xa6/0x1c0
        entry_SYSCALL64_slow_path+0x25/0x25
       ---[ end trace bd187ee0267df5d9 ]---
    
    To avoid this, set link->downstream in alloc_pcie_link_state(), so every
    pcie_link_state structure has a valid link->downstream pointer.
    
    [bhelgaas: changelog]
    Signed-off-by: default avatarYinghai Lu <yinghai@kernel.org>
    Signed-off-by: default avatarBjorn Helgaas <bhelgaas@google.com>
    Acked-by: default avatarRajat Jain <rajatja@google.com>
    CC: stable@vger.kernel.org
    3bd7db63
Name
Last commit
Last update
..
dwc Loading commit data...
host Loading commit data...
hotplug Loading commit data...
pcie Loading commit data...
Kconfig Loading commit data...
Makefile Loading commit data...
access.c Loading commit data...
ats.c Loading commit data...
bus.c Loading commit data...
ecam.c Loading commit data...
host-bridge.c Loading commit data...
hotplug-pci.c Loading commit data...
htirq.c Loading commit data...
iov.c Loading commit data...
irq.c Loading commit data...
msi.c Loading commit data...
of.c Loading commit data...
pci-acpi.c Loading commit data...
pci-driver.c Loading commit data...
pci-label.c Loading commit data...
pci-mid.c Loading commit data...
pci-stub.c Loading commit data...
pci-sysfs.c Loading commit data...
pci.c Loading commit data...
pci.h Loading commit data...
probe.c Loading commit data...
proc.c Loading commit data...
quirks.c Loading commit data...
remove.c Loading commit data...
rom.c Loading commit data...
search.c Loading commit data...
setup-bus.c Loading commit data...
setup-irq.c Loading commit data...
setup-res.c Loading commit data...
slot.c Loading commit data...
syscall.c Loading commit data...
vc.c Loading commit data...
vpd.c Loading commit data...
xen-pcifront.c Loading commit data...