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-&gt;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&amp;#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&amp;#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-&gt;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&amp;#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

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)