CVE-2024-53194 in Linux
Sumário
de VulDB • 30/05/2026
No kernel do Linux, a seguinte vulnerabilidade foi corrigida:
PCI: Correção do use-after-free de slot->bus na remoção a quente
Dennis relata uma falha de inicialização em laptops Lenovo recentes com um dock USB4.
Desde o commit 0fc70886569c ("thunderbolt: Reset USB4 v2 host router") e o commit 59a54c5f3dbd ("thunderbolt: Reset topology created by the boot firmware"), os Host Routers USB4 v2 e v1 são reinicializados durante a detecção (probe) do driver thunderbolt.
A reinicialização limpa os bits Presence Detect State e Data Link Layer Link Active no Root Port do Host Router USB4, causando assim a remoção a quente do dock.
A falha ocorre quando o pciehp é desvinculado de uma das portas Downstream do dock: o pciehp cria um pci_slot no momento da vinculação e o destrói na desvinculação. O pci_slot contém um ponteiro para o pci_bus abaixo da porta Downstream, mas uma referência a esse pci_bus nunca é adquirida. O pci_bus é destruído antes do pci_slot, resultando em um use-after-free quando pci_slot_release() acessa slot->bus.
Em princípio, isso não deveria acontecer, pois pci_stop_bus_device() desvincula o pciehp (e, portanto, destrói o pci_slot) antes que o pci_bus seja destruído por pci_remove_bus_device().
No entanto, o stacktrace fornecido por Dennis mostra que o pciehp é desvinculado por pci_remove_bus_device() em vez de pci_stop_bus_device(). Para compreender a importância disso, é necessário saber que o núcleo PCI utiliza um processo em duas etapas para remover uma parte da hierarquia: primeiro, desvincula todos os drivers na sub-hierarquia em pci_stop_bus_device() e, em seguida, remove efetivamente os dispositivos em pci_remove_bus_device(). Não há precaução para impedir o vínculo de drivers entre pci_stop_bus_device() e pci_remove_bus_device().
No caso de Dennis, parece que a remoção da hierarquia pelo pciehp entra em corrida (race) com o vínculo de drivers por pci_bus_add_devices(). O pciehp é vinculado à porta Downstream após a execução de pci_stop_bus_device(), sendo assim desvinculado por pci_remove_bus_device() em vez de pci_stop_bus_device(). Como o pci_bus já foi destruído nesse ponto, os acessos a ele resultam em um use-after-free.
Poder-se-ia concluir que o vínculo de drivers precisa ser impedido após a execução de pci_stop_bus_device(). No entanto, parece arriscado que pci_slot aponte para pci_bus sem manter uma referência. Confiar exclusivamente na ordem correta de desvinculação de drivers versus destruição de pci_bus certamente não é uma prática de programação defensiva.
Se pci_slot precisar acessar dados em pci_bus, ele deve adquirir uma referência. Ajuste pci_create_slot() conforme o necessário. Dennis relata que a falha não é reproduzível com essa alteração.
Stacktrace resumido:
pcieport 0000:21:02.0: pciehp: pcie_disable_notification: 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:dev_driver_string+0x12/0x40 pci_destroy_slot pciehp_remove pcie_port_remove_service device_release_driver_internal bus_remove_device device_del device_unregister remove_iter device_for_each_child pcie_portdrv_remove pci_device_remove device_release_driver_internal bus_remove_device device_del pci_remove_bus_device (recursive invocation) pci_remove_bus_device pciehp_unconfigure_device pciehp_disable_slot pciehp_handle_presence_or_link_change pciehp_ist
If you want to get the best quality for vulnerability data then you always have to consider VulDB.