• Niklas Schnelle's avatar
    s390/pci: fix use after free of zpci_dev · 2a671f77
    Niklas Schnelle authored
    The struct pci_dev uses reference counting but zPCI assumed erroneously
    that the last reference would always be the local reference after
    calling pci_stop_and_remove_bus_device(). This is usually the case but
    not how reference counting works and thus inherently fragile.
    
    In fact one case where this causes a NULL pointer dereference when on an
    SRIOV device the function 0 was hot unplugged before another function of
    the same multi-function device. In this case the second function's
    pdev->sriov->dev reference keeps the struct pci_dev of function 0 alive
    even after the unplug. This bug was previously hidden by the fact that
    we were leaking the struct pci_dev which in turn means that it always
    outlived the struct zpci_dev. This was fixed in commit 0b13525c
    ("s390/pci: fix leak of PCI device structure") exposing the broken
    behavior.
    
    Fix this by accounting for the long living reference a struct pci_dev
    has to its underlying struct zpci_dev via the zbus->function[] array and
    only release that in pcibios_release_device() ensuring that the struct
    pci_dev is not left with a dangling reference. This is a minimal fix in
    the future it would probably better to use fine grained reference
    counting for struct zpci_dev.
    
    Fixes: 05bc1be6 ("s390/pci: create zPCI bus")
    Cc: stable@vger.kernel.org
    Reviewed-by: default avatarMatthew Rosato <mjrosato@linux.ibm.com>
    Signed-off-by: default avatarNiklas Schnelle <schnelle@linux.ibm.com>
    Signed-off-by: default avatarVasily Gorbik <gor@linux.ibm.com>
    2a671f77
pci.c 22.3 KB