]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
PCI: Avoid reset when disabled via sysfs
authorNishanth Aravamudan <naravamudan@nvidia.com>
Fri, 7 Feb 2025 20:56:00 +0000 (14:56 -0600)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 10 Apr 2025 12:39:15 +0000 (14:39 +0200)
[ Upstream commit 479380efe1625e251008d24b2810283db60d6fcd ]

After d88f521da3ef ("PCI: Allow userspace to query and set device reset
mechanism"), userspace can disable reset of specific PCI devices by writing
an empty string to the sysfs reset_method file.

However, pci_slot_resettable() does not check pci_reset_supported(), which
means that pci_reset_function() will still reset the device even if
userspace has disabled all the reset methods.

I was able to reproduce this issue with a vfio device passed to a qemu
guest, where I had disabled PCI reset via sysfs.

Add an explicit check of pci_reset_supported() in both
pci_slot_resettable() and pci_bus_resettable() to ensure both the reset
status and reset execution are bypassed if an administrator disables it for
a device.

Link: https://lore.kernel.org/r/20250207205600.1846178-1-naravamudan@nvidia.com
Fixes: d88f521da3ef ("PCI: Allow userspace to query and set device reset mechanism")
Signed-off-by: Nishanth Aravamudan <naravamudan@nvidia.com>
[bhelgaas: commit log]
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Cc: Alex Williamson <alex.williamson@redhat.com>
Cc: Raphael Norwitz <raphael.norwitz@nutanix.com>
Cc: Amey Narkhede <ameynarkhede03@gmail.com>
Cc: Jason Gunthorpe <jgg@nvidia.com>
Cc: Yishai Hadas <yishaih@nvidia.com>
Cc: Shameer Kolothum <shameerali.kolothum.thodi@huawei.com>
Cc: Kevin Tian <kevin.tian@intel.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/pci/pci.c

index 25211d12192278ba1eb71b63b1651feff3c560a9..169aa8fd74a11f4848fa7ab97d7b8ec92a0373f5 100644 (file)
@@ -5528,6 +5528,8 @@ static bool pci_bus_resettable(struct pci_bus *bus)
                return false;
 
        list_for_each_entry(dev, &bus->devices, bus_list) {
+               if (!pci_reset_supported(dev))
+                       return false;
                if (dev->dev_flags & PCI_DEV_FLAGS_NO_BUS_RESET ||
                    (dev->subordinate && !pci_bus_resettable(dev->subordinate)))
                        return false;
@@ -5604,6 +5606,8 @@ static bool pci_slot_resettable(struct pci_slot *slot)
        list_for_each_entry(dev, &slot->bus->devices, bus_list) {
                if (!dev->slot || dev->slot != slot)
                        continue;
+               if (!pci_reset_supported(dev))
+                       return false;
                if (dev->dev_flags & PCI_DEV_FLAGS_NO_BUS_RESET ||
                    (dev->subordinate && !pci_bus_resettable(dev->subordinate)))
                        return false;