CVE-2024-53194
Severity CVSS v4.0:
Pending analysis
Type:
CWE-416
Use After Free
Publication date:
27/12/2024
Last modified:
24/03/2025
Description
In the Linux kernel, the following vulnerability has been resolved:<br />
<br />
PCI: Fix use-after-free of slot->bus on hot remove<br />
<br />
Dennis reports a boot crash on recent Lenovo laptops with a USB4 dock.<br />
<br />
Since commit 0fc70886569c ("thunderbolt: Reset USB4 v2 host router") and<br />
commit 59a54c5f3dbd ("thunderbolt: Reset topology created by the boot<br />
firmware"), USB4 v2 and v1 Host Routers are reset on probe of the<br />
thunderbolt driver.<br />
<br />
The reset clears the Presence Detect State and Data Link Layer Link Active<br />
bits at the USB4 Host Router&#39;s Root Port and thus causes hot removal of the<br />
dock.<br />
<br />
The crash occurs when pciehp is unbound from one of the dock&#39;s Downstream<br />
Ports: pciehp creates a pci_slot on bind and destroys it on unbind. The<br />
pci_slot contains a pointer to the pci_bus below the Downstream Port, but<br />
a reference on that pci_bus is never acquired. The pci_bus is destroyed<br />
before the pci_slot, so a use-after-free ensues when pci_slot_release()<br />
accesses slot->bus.<br />
<br />
In principle this should not happen because pci_stop_bus_device() unbinds<br />
pciehp (and therefore destroys the pci_slot) before the pci_bus is<br />
destroyed by pci_remove_bus_device().<br />
<br />
However the stacktrace provided by Dennis shows that pciehp is unbound from<br />
pci_remove_bus_device() instead of pci_stop_bus_device(). To understand<br />
the significance of this, one needs to know that the PCI core uses a two<br />
step process to remove a portion of the hierarchy: It first unbinds all<br />
drivers in the sub-hierarchy in pci_stop_bus_device() and then actually<br />
removes the devices in pci_remove_bus_device(). There is no precaution to<br />
prevent driver binding in-between pci_stop_bus_device() and<br />
pci_remove_bus_device().<br />
<br />
In Dennis&#39; case, it seems removal of the hierarchy by pciehp races with<br />
driver binding by pci_bus_add_devices(). pciehp is bound to the<br />
Downstream Port after pci_stop_bus_device() has run, so it is unbound by<br />
pci_remove_bus_device() instead of pci_stop_bus_device(). Because the<br />
pci_bus has already been destroyed at that point, accesses to it result in<br />
a use-after-free.<br />
<br />
One might conclude that driver binding needs to be prevented after<br />
pci_stop_bus_device() has run. However it seems risky that pci_slot points<br />
to pci_bus without holding a reference. Solely relying on correct ordering<br />
of driver unbind versus pci_bus destruction is certainly not defensive<br />
programming.<br />
<br />
If pci_slot has a need to access data in pci_bus, it ought to acquire a<br />
reference. Amend pci_create_slot() accordingly. Dennis reports that the<br />
crash is not reproducible with this change.<br />
<br />
Abridged stacktrace:<br />
<br />
pcieport 0000:00:07.0: PME: Signaling with IRQ 156<br />
pcieport 0000:00:07.0: pciehp: Slot #12 AttnBtn- PwrCtrl- MRL- AttnInd- PwrInd- HotPlug+ Surprise+ Interlock- NoCompl+ IbPresDis- LLActRep+<br />
pci_bus 0000:20: dev 00, created physical slot 12<br />
pcieport 0000:00:07.0: pciehp: Slot(12): Card not present<br />
...<br />
pcieport 0000:21:02.0: pciehp: pcie_disable_notification: SLOTCTRL d8 write cmd 0<br />
Oops: general protection fault, probably for non-canonical address 0x6b6b6b6b6b6b6b6b: 0000 [#1] PREEMPT SMP NOPTI<br />
CPU: 13 UID: 0 PID: 134 Comm: irq/156-pciehp Not tainted 6.11.0-devel+ #1<br />
RIP: 0010:dev_driver_string+0x12/0x40<br />
pci_destroy_slot<br />
pciehp_remove<br />
pcie_port_remove_service<br />
device_release_driver_internal<br />
bus_remove_device<br />
device_del<br />
device_unregister<br />
remove_iter<br />
device_for_each_child<br />
pcie_portdrv_remove<br />
pci_device_remove<br />
device_release_driver_internal<br />
bus_remove_device<br />
device_del<br />
pci_remove_bus_device (recursive invocation)<br />
pci_remove_bus_device<br />
pciehp_unconfigure_device<br />
pciehp_disable_slot<br />
pciehp_handle_presence_or_link_change<br />
pciehp_ist
Impact
Base Score 3.x
7.80
Severity 3.x
HIGH
Vulnerable products and versions
CPE | From | Up to |
---|---|---|
cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:* | 4.19.325 (excluding) | |
cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:* | 4.20 (including) | 5.4.287 (excluding) |
cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:* | 5.5 (including) | 5.10.231 (excluding) |
cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:* | 5.11 (including) | 5.15.174 (excluding) |
cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:* | 5.16 (including) | 6.1.120 (excluding) |
cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:* | 6.2 (including) | 6.6.64 (excluding) |
cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:* | 6.7 (including) | 6.11.11 (excluding) |
cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:* | 6.12 (including) | 6.12.2 (excluding) |
To consult the complete list of CPE names with products and versions, see this page
References to Advisories, Solutions, and Tools
- https://git.kernel.org/stable/c/20502f0b3f3acd6bee300257556c27a867f80c8b
- https://git.kernel.org/stable/c/41bbb1eb996be1435815aa1fbcc9ffc45b84cc12
- https://git.kernel.org/stable/c/50473dd3b2a08601a078f852ea05572de9b1f86c
- https://git.kernel.org/stable/c/69d2ceac11acf8579d58d55c9c5b65fb658f916e
- https://git.kernel.org/stable/c/c7acef99642b763ba585f4a43af999fcdbcc3dc4
- https://git.kernel.org/stable/c/c8266ab8e7ccd1d1f5a9c8b29eb2020175048134
- https://git.kernel.org/stable/c/d0ddd2c92b75a19a37c887154223372b600fed37
- https://git.kernel.org/stable/c/da6e6ff1f6c57f16e07af955e0e997fc90dd1e75
- https://git.kernel.org/stable/c/e5d5c04aac71bf1476dc44b56f2206a4c2facca8