lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Date:   Mon, 4 Apr 2022 14:25:39 +0800
From:   Jay Zhou <jianjay.zhou@...wei.com>
To:     <linux-pci@...r.kernel.org>, <linux-kernel@...r.kernel.org>,
        <bhelgaas@...gle.com>, <alex.williamson@...hat.com>
CC:     <weidong.huang@...wei.com>, <jianjay.zhou@...wei.com>
Subject: [PATCH] pci: avoid dead lock between device reset and sriov disable

Call trace of PF SRIOV disable:
sriov_numvfs_store
  device_lock <----------------- (1) get the device lock
    ->sriov_configure # e.g. vfio_pci_sriov_configure
      sriov_disable
        pci_cfg_access_lock <--- (4) wait dev->block_cfg_access to be 0

Call trace of PF reset:
reset_store
  pci_reset_function
    pci_dev_lock
      pci_cfg_access_lock <----- (2) set dev->block_cfg_access = 1
      device_lock <------------- (3) want to get the device lock

These two oprations would wait for each other forever if the
code execution sequence is (1)(2)(3)(4).

Let's get the device lock and then the config access lock in
pci_dev_lock().

Signed-off-by: Jay Zhou <jianjay.zhou@...wei.com>
---
 drivers/pci/pci.c | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 9ecce435fb3f..61a6db1d21f6 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -5103,19 +5103,19 @@ static int pci_reset_bus_function(struct pci_dev *dev, bool probe)
 
 void pci_dev_lock(struct pci_dev *dev)
 {
-	pci_cfg_access_lock(dev);
 	/* block PM suspend, driver probe, etc. */
 	device_lock(&dev->dev);
+	pci_cfg_access_lock(dev);
 }
 EXPORT_SYMBOL_GPL(pci_dev_lock);
 
 /* Return 1 on successful lock, 0 on contention */
 int pci_dev_trylock(struct pci_dev *dev)
 {
-	if (pci_cfg_access_trylock(dev)) {
-		if (device_trylock(&dev->dev))
+	if (device_trylock(&dev->dev)) {
+		if (pci_cfg_access_trylock(dev))
 			return 1;
-		pci_cfg_access_unlock(dev);
+		device_unlock(&dev->dev);
 	}
 
 	return 0;
@@ -5124,8 +5124,8 @@ EXPORT_SYMBOL_GPL(pci_dev_trylock);
 
 void pci_dev_unlock(struct pci_dev *dev)
 {
-	device_unlock(&dev->dev);
 	pci_cfg_access_unlock(dev);
+	device_unlock(&dev->dev);
 }
 EXPORT_SYMBOL_GPL(pci_dev_unlock);
 
-- 
2.27.0

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ