CVE-2024-53194

Source
https://cve.org/CVERecord?id=CVE-2024-53194
Import Source
https://storage.googleapis.com/osv-test-cve-osv-conversion/osv-output/CVE-2024-53194.json
JSON Data
https://api.test.osv.dev/v1/vulns/CVE-2024-53194
Downstream
Related
Published
2024-12-27T13:49:36.534Z
Modified
2026-03-20T12:40:47.897810Z
Severity
  • 7.8 (High) CVSS_V3 - CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H CVSS Calculator
Summary
PCI: Fix use-after-free of slot->bus on hot remove
Details

In the Linux kernel, the following vulnerability has been resolved:

PCI: Fix use-after-free of slot->bus on hot remove

Dennis reports a boot crash on recent Lenovo laptops with a USB4 dock.

Since commit 0fc70886569c ("thunderbolt: Reset USB4 v2 host router") and commit 59a54c5f3dbd ("thunderbolt: Reset topology created by the boot firmware"), USB4 v2 and v1 Host Routers are reset on probe of the thunderbolt driver.

The reset clears the Presence Detect State and Data Link Layer Link Active bits at the USB4 Host Router's Root Port and thus causes hot removal of the dock.

The crash occurs when pciehp is unbound from one of the dock's Downstream Ports: pciehp creates a pcislot on bind and destroys it on unbind. The pcislot contains a pointer to the pcibus below the Downstream Port, but a reference on that pcibus is never acquired. The pcibus is destroyed before the pcislot, so a use-after-free ensues when pcislotrelease() accesses slot->bus.

In principle this should not happen because pcistopbusdevice() unbinds pciehp (and therefore destroys the pcislot) before the pcibus is destroyed by pciremovebusdevice().

However the stacktrace provided by Dennis shows that pciehp is unbound from pciremovebusdevice() instead of pcistopbusdevice(). To understand the significance of this, one needs to know that the PCI core uses a two step process to remove a portion of the hierarchy: It first unbinds all drivers in the sub-hierarchy in pcistopbusdevice() and then actually removes the devices in pciremovebusdevice(). There is no precaution to prevent driver binding in-between pcistopbusdevice() and pciremovebusdevice().

In Dennis' case, it seems removal of the hierarchy by pciehp races with driver binding by pcibusadddevices(). pciehp is bound to the Downstream Port after pcistopbusdevice() has run, so it is unbound by pciremovebusdevice() instead of pcistopbusdevice(). Because the pci_bus has already been destroyed at that point, accesses to it result in a use-after-free.

One might conclude that driver binding needs to be prevented after pcistopbusdevice() has run. However it seems risky that pcislot points to pcibus without holding a reference. Solely relying on correct ordering of driver unbind versus pcibus destruction is certainly not defensive programming.

If pcislot has a need to access data in pcibus, it ought to acquire a reference. Amend pcicreateslot() accordingly. Dennis reports that the crash is not reproducible with this change.

Abridged stacktrace:

pcieport 0000:00:07.0: PME: Signaling with IRQ 156 pcieport 0000:00:07.0: pciehp: Slot #12 AttnBtn- PwrCtrl- MRL- AttnInd- PwrInd- HotPlug+ Surprise+ Interlock- NoCompl+ IbPresDis- LLActRep+ pcibus 0000:20: dev 00, created physical slot 12 pcieport 0000:00:07.0: pciehp: Slot(12): Card not present ... pcieport 0000:21:02.0: pciehp: pciedisablenotification: SLOTCTRL d8 write cmd 0 Oops: general protection fault, probably for non-canonical address 0x6b6b6b6b6b6b6b6b: 0000 [#1] PREEMPT SMP NOPTI CPU: 13 UID: 0 PID: 134 Comm: irq/156-pciehp Not tainted 6.11.0-devel+ #1 RIP: 0010:devdriverstring+0x12/0x40 pcidestroyslot pciehpremove pcieportremoveservice devicereleasedriverinternal busremovedevice devicedel deviceunregister removeiter deviceforeachchild pcieportdrvremove pcideviceremove devicereleasedriverinternal busremovedevice devicedel pciremovebusdevice (recursive invocation) pciremovebusdevice pciehpunconfiguredevice pciehpdisableslot pciehphandlepresenceorlinkchange pciehpist

Database specific
{
    "cna_assigner": "Linux",
    "osv_generated_from": "https://github.com/CVEProject/cvelistV5/tree/main/cves/2024/53xxx/CVE-2024-53194.json"
}
References

Affected packages

Git / git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git

Affected ranges

Type
GIT
Repo
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
Events
Introduced
f46753c5e354b857b20ab8e0fe7b2579831dc369
Fixed
50473dd3b2a08601a078f852ea05572de9b1f86c
Fixed
d0ddd2c92b75a19a37c887154223372b600fed37
Fixed
da6e6ff1f6c57f16e07af955e0e997fc90dd1e75
Fixed
41bbb1eb996be1435815aa1fbcc9ffc45b84cc12
Fixed
20502f0b3f3acd6bee300257556c27a867f80c8b
Fixed
e5d5c04aac71bf1476dc44b56f2206a4c2facca8
Fixed
c8266ab8e7ccd1d1f5a9c8b29eb2020175048134
Fixed
69d2ceac11acf8579d58d55c9c5b65fb658f916e
Fixed
c7acef99642b763ba585f4a43af999fcdbcc3dc4

Database specific

source
"https://storage.googleapis.com/osv-test-cve-osv-conversion/osv-output/CVE-2024-53194.json"