lkml.org 
[lkml]   [2013]   [Aug]   [8]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[ 070/102] PCI: pciehp: Fix null pointer deref when hot-removing SR-IOV device
    Date
    3.10-stable review patch.  If anyone has any objections, please let me know.

    ------------------

    From: Yinghai Lu <yinghai@kernel.org>

    commit 29ed1f29b68a8395d5679b3c4e38352b617b3236 upstream.

    Hot-removing a device with SR-IOV enabled causes a null pointer dereference
    in v3.9 and v3.10.

    This is a regression caused by ba518e3c17 ("PCI: pciehp: Iterate over all
    devices in slot, not functions 0-7"). When we iterate over the
    bus->devices list, we first remove the PF, which also removes all the VFs
    from the list. Then the list iterator blows up because more than just the
    current entry was removed from the list.

    ac205b7bb7 ("PCI: make sriov work with hotplug remove") works around a
    similar problem in pci_stop_bus_devices() by iterating over the list in
    reverse, so the VFs are stopped and removed from the list first, before the
    PF.

    This patch changes pciehp_unconfigure_device() to iterate over the list in
    reverse, too.

    [bhelgaas: bugzilla, changelog]
    Reference: https://bugzilla.kernel.org/show_bug.cgi?id=60604
    Signed-off-by: Yinghai Lu <yinghai@kernel.org>
    Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
    Acked-by: Yijing Wang <wangyijing@huawei.com>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

    ---
    drivers/pci/hotplug/pciehp_pci.c | 9 ++++++++-
    1 file changed, 8 insertions(+), 1 deletion(-)

    --- a/drivers/pci/hotplug/pciehp_pci.c
    +++ b/drivers/pci/hotplug/pciehp_pci.c
    @@ -92,7 +92,14 @@ int pciehp_unconfigure_device(struct slo
    if (ret)
    presence = 0;

    - list_for_each_entry_safe(dev, temp, &parent->devices, bus_list) {
    + /*
    + * Stopping an SR-IOV PF device removes all the associated VFs,
    + * which will update the bus->devices list and confuse the
    + * iterator. Therefore, iterate in reverse so we remove the VFs
    + * first, then the PF. We do the same in pci_stop_bus_device().
    + */
    + list_for_each_entry_safe_reverse(dev, temp, &parent->devices,
    + bus_list) {
    pci_dev_get(dev);
    if (dev->hdr_type == PCI_HEADER_TYPE_BRIDGE && presence) {
    pci_read_config_byte(dev, PCI_BRIDGE_CONTROL, &bctl);



    \
     
     \ /
      Last update: 2013-08-09 05:01    [W:4.448 / U:0.068 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site