Re: [PATCH] PCI/ASPM: fix UAF by disable ASPM for link when child function is removed

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]


On 2023/5/5 10:51, Sathyanarayanan Kuppuswamy wrote:

On 5/4/23 5:34 AM, Ding Hui wrote:

Maybe you can use the following title?

"PCI/ASPM: Fix UAF by disabling ASPM for link when child function is removed

Thanks, I'll fix it in next patch.

If the Function 0 of a Multi-Function device is software removed,
a freed downstream pointer will be left in struct pcie_link_state,
and then when pcie_config_aspm_link() be invoked from any path,
we will trigger use-after-free.

Based on the PCIe spec about ASPM Control (PCIe r6.0, sec,

As per PCIe spec r6.0, sec, it is recommended

Thanks, I'll fix it in next patch.

for Multi-Function Devices (including ARI Devices), it is recommended
that software program the same value in all Functions. For ARI
Devices, ASPM Control is determined solely by the setting in Function 0.

So we can just disable ASPM of the whole component if any child
function is removed, the downstream pointer will be avoided from
use-after-free, that will also avoid other potential corner cases.

Fixes: b5a0a9b59c81 ("PCI/ASPM: Read and set up L1 substate capabilities")
Debugged-by: Zongquan Qin <qinzongquan@xxxxxxxxxxxxxx>

Any bugzilla link with error log and reproduction steps?

Yes, I should link previous

Since Bjorn think the ALL details is not necessary, so I'll add the
reproducer and compact result in next patch.

Suggestion-by: Bjorn Helgaas <bhelgaas@xxxxxxxxxx>


Sorry, I'll fix it in next patch.

Signed-off-by: Ding Hui <dinghui@xxxxxxxxxxxxxx>
  drivers/pci/pcie/aspm.c | 15 +++++++--------
  1 file changed, 7 insertions(+), 8 deletions(-)

diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c
index 66d7514ca111..1bf8306141aa 100644
--- a/drivers/pci/pcie/aspm.c
+++ b/drivers/pci/pcie/aspm.c
@@ -1010,18 +1010,17 @@ void pcie_aspm_exit_link_state(struct pci_dev *pdev)
-	/*
-	 * All PCIe functions are in one slot, remove one function will remove
-	 * the whole slot, so just wait until we are the last function left.
-	 */
-	if (!list_empty(&parent->subordinate->devices))
-		goto out;
link = parent->link_state;
  	root = link->root;
  	parent_link = link->parent;
- /* All functions are removed, so just disable ASPM for the link */
+	/*
+	 * Any function is removed (including software removing), just
+	 * disable ASPM for the link, in case we can not configure the same
+	 * setting for all functions.

How about following?

  * For any function removed, disable ASPM for the link. See PCIe r6.0,
  * sec for details.

Thanks, it's better.

+	 * See PCIe r6.0, sec
+	 */
  	pcie_config_aspm_link(link, 0);
  	/* Clock PM is for endpoint device */
@@ -1032,7 +1031,7 @@ void pcie_aspm_exit_link_state(struct pci_dev *pdev)

- Ding Hui

[Index of Archives]     [DMA Engine]     [Linux Coverity]     [Linux USB]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Greybus]

  Powered by Linux