• Niklas Schnelle's avatar
    s390/pci: fix zpci_zdev_put() on reserve · a46044a9
    Niklas Schnelle authored
    Since commit 2a671f77 ("s390/pci: fix use after free of zpci_dev")
    the reference count of a zpci_dev is incremented between
    pcibios_add_device() and pcibios_release_device() which was supposed to
    prevent the zpci_dev from being freed while the common PCI code has
    access to it. It was missed however that the handling of zPCI
    availability events assumed that once zpci_zdev_put() was called no
    later availability event would still see the device. With the previously
    mentioned commit however this assumption no longer holds and we must
    make sure that we only drop the initial long-lived reference the zPCI
    subsystem holds exactly once.
    
    Do so by introducing a zpci_device_reserved() function that handles when
    a device is reserved. Here we make sure the zpci_dev will not be
    considered for further events by removing it from the zpci_list.
    
    This also means that the device actually stays in the
    ZPCI_FN_STATE_RESERVED state between the time we know it has been
    reserved and the final reference going away. We thus need to consider it
    a real state instead of just a conceptual state after the removal. The
    final cleanup of PCI resources, removal from zbus, and destruction of
    the IOMMU stays in zpci_release_device() to make sure holders of the
    reference do see valid data until the release.
    
    Fixes: 2a671f77 ("s390/pci: fix use after free of zpci_dev")
    Cc: stable@vger.kernel.org
    Signed-off-by: default avatarNiklas Schnelle <schnelle@linux.ibm.com>
    Signed-off-by: default avatarVasily Gorbik <gor@linux.ibm.com>
    a46044a9
pci.c 23.8 KB