CVE-2025-40219
Publication date:
04/12/2025
In the Linux kernel, the following vulnerability has been resolved:<br />
<br />
PCI/IOV: Add PCI rescan-remove locking when enabling/disabling SR-IOV<br />
<br />
Before disabling SR-IOV via config space accesses to the parent PF,<br />
sriov_disable() first removes the PCI devices representing the VFs.<br />
<br />
Since commit 9d16947b7583 ("PCI: Add global pci_lock_rescan_remove()")<br />
such removal operations are serialized against concurrent remove and<br />
rescan using the pci_rescan_remove_lock. No such locking was ever added<br />
in sriov_disable() however. In particular when commit 18f9e9d150fc<br />
("PCI/IOV: Factor out sriov_add_vfs()") factored out the PCI device<br />
removal into sriov_del_vfs() there was still no locking around the<br />
pci_iov_remove_virtfn() calls.<br />
<br />
On s390 the lack of serialization in sriov_disable() may cause double<br />
remove and list corruption with the below (amended) trace being observed:<br />
<br />
PSW: 0704c00180000000 0000000c914e4b38 (klist_put+56)<br />
GPRS: 000003800313fb48 0000000000000000 0000000100000001 0000000000000001<br />
00000000f9b520a8 0000000000000000 0000000000002fbd 00000000f4cc9480<br />
0000000000000001 0000000000000000 0000000000000000 0000000180692828<br />
00000000818e8000 000003800313fe2c 000003800313fb20 000003800313fad8<br />
#0 [3800313fb20] device_del at c9158ad5c<br />
#1 [3800313fb88] pci_remove_bus_device at c915105ba<br />
#2 [3800313fbd0] pci_iov_remove_virtfn at c9152f198<br />
#3 [3800313fc28] zpci_iov_remove_virtfn at c90fb67c0<br />
#4 [3800313fc60] zpci_bus_remove_device at c90fb6104<br />
#5 [3800313fca0] __zpci_event_availability at c90fb3dca<br />
#6 [3800313fd08] chsc_process_sei_nt0 at c918fe4a2<br />
#7 [3800313fd60] crw_collect_info at c91905822<br />
#8 [3800313fe10] kthread at c90feb390<br />
#9 [3800313fe68] __ret_from_fork at c90f6aa64<br />
#10 [3800313fe98] ret_from_fork at c9194f3f2.<br />
<br />
This is because in addition to sriov_disable() removing the VFs, the<br />
platform also generates hot-unplug events for the VFs. This being the<br />
reverse operation to the hotplug events generated by sriov_enable() and<br />
handled via pdev->no_vf_scan. And while the event processing takes<br />
pci_rescan_remove_lock and checks whether the struct pci_dev still exists,<br />
the lack of synchronization makes this checking racy.<br />
<br />
Other races may also be possible of course though given that this lack of<br />
locking persisted so long observable races seem very rare. Even on s390 the<br />
list corruption was only observed with certain devices since the platform<br />
events are only triggered by config accesses after the removal, so as long<br />
as the removal finished synchronously they would not race. Either way the<br />
locking is missing so fix this by adding it to the sriov_del_vfs() helper.<br />
<br />
Just like PCI rescan-remove, locking is also missing in sriov_add_vfs()<br />
including for the error case where pci_stop_and_remove_bus_device() is<br />
called without the PCI rescan-remove lock being held. Even in the non-error<br />
case, adding new PCI devices and buses should be serialized via the PCI<br />
rescan-remove lock. Add the necessary locking.
Severity CVSS v4.0: Pending analysis
Last modification:
04/12/2025