Commit 951c5e26 authored by Jay Fang's avatar Jay Fang Committed by lujunhua
Browse files

PCI/ASPM: Update ASPM sysfs on MFD function removal to avoid use-after-free

driver inclusion
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/IB2LVJ
CVE: NA

--------------------------------

From 'commit 456d8aa3 ("PCI/ASPM: Disable ASPM on MFD function removal
to avoid use-after-free")' we know that PCIe spec r6.0, sec 7.5.3.7,
recommends that software program the same ASPM Control(pcie_link_state)
value in all functions of multi-function devices, and free the
pcie_link_state when any child function is removed.

However, ASPM Control sysfs is still visible to other children even if it
has been removed by any child function, and careless use it will
trigger use-after-free error, e.g.:

  # lspci -tv
    -[0000:16]---00.0-[17]--+-00.0  Device 19e5:0222
                            \-00.1  Device 19e5:0222
  # echo 1 > /sys/bus/pci/devices/0000:17:00.0/remove
  //pcie_link_state will be released
  # echo 1 > /sys/bus/pci/devices/0000:17:00.1/link/l1_aspm
  //will trigger error

Unable to handle kernel NULL pointer dereference at virtual
address 0000000000000030 Call trace:
aspm_attr_store_common.constprop.0+0x10c/0x154
l1_aspm_store+0x24/0x30
dev_attr_store+0x20/0x34
sysfs_kf_write+0x4c/0x5c

We can solve this problem by updating the ASPM Control sysfs of all
children immediately after ASPM Control have been freed.

Extra note: The Linux community plans to optimize to the pcie_link_state
management code.For details,see the following link:
https://patchwork.kernel.org/project/linux-pci/patch/


20240730011639.2590846-1-f.fangjian@huawei.com/

Fixes: 456d8aa3 ("PCI/ASPM: Disable ASPM on MFD function removal to avoid use-after-free")
Signed-off-by: default avatarJay Fang <f.fangjian@huawei.com>
Signed-off-by: default avatarlujunhua <lujunhua7@h-partners.com>
parent b8723410
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -997,6 +997,8 @@ void pcie_aspm_exit_link_state(struct pci_dev *pdev)
		pcie_config_aspm_path(parent_link);
	}

	pcie_aspm_update_sysfs_visibility(parent);

	mutex_unlock(&aspm_lock);
	up_read(&pci_bus_sem);
}