Instituto Nacional de ciberseguridad. Sección Incibe
Instituto Nacional de Ciberseguridad. Sección INCIBE-CERT

CVE-2026-31530

Gravedad:
Pendiente de análisis
Tipo:
No Disponible / Otro tipo
Fecha de publicación:
22/04/2026
Última modificación:
22/04/2026

Descripción

*** Pendiente de traducción *** In the Linux kernel, the following vulnerability has been resolved:<br /> <br /> cxl/port: Fix use after free of parent_port in cxl_detach_ep()<br /> <br /> cxl_detach_ep() is called during bottom-up removal when all CXL memory<br /> devices beneath a switch port have been removed. For each port in the<br /> hierarchy it locks both the port and its parent, removes the endpoint,<br /> and if the port is now empty, marks it dead and unregisters the port<br /> by calling delete_switch_port(). There are two places during this work<br /> where the parent_port may be used after freeing:<br /> <br /> First, a concurrent detach may have already processed a port by the<br /> time a second worker finds it via bus_find_device(). Without pinning<br /> parent_port, it may already be freed when we discover port-&gt;dead and<br /> attempt to unlock the parent_port. In a production kernel that&amp;#39;s a<br /> silent memory corruption, with lock debug, it looks like this:<br /> <br /> []DEBUG_LOCKS_WARN_ON(__owner_task(owner) != get_current())<br /> []WARNING: kernel/locking/mutex.c:949 at __mutex_unlock_slowpath+0x1ee/0x310<br /> []Call Trace:<br /> []mutex_unlock+0xd/0x20<br /> []cxl_detach_ep+0x180/0x400 [cxl_core]<br /> []devm_action_release+0x10/0x20<br /> []devres_release_all+0xa8/0xe0<br /> []device_unbind_cleanup+0xd/0xa0<br /> []really_probe+0x1a6/0x3e0<br /> <br /> Second, delete_switch_port() releases three devm actions registered<br /> against parent_port. The last of those is unregister_port() and it<br /> calls device_unregister() on the child port, which can cascade. If<br /> parent_port is now also empty the device core may unregister and free<br /> it too. So by the time delete_switch_port() returns, parent_port may<br /> be free, and the subsequent device_unlock(&amp;parent_port-&gt;dev) operates<br /> on freed memory. The kernel log looks same as above, with a different<br /> offset in cxl_detach_ep().<br /> <br /> Both of these issues stem from the absence of a lifetime guarantee<br /> between a child port and its parent port.<br /> <br /> Establish a lifetime rule for ports: child ports hold a reference to<br /> their parent device until release. Take the reference when the port<br /> is allocated and drop it when released. This ensures the parent is<br /> valid for the full lifetime of the child and eliminates the use after<br /> free window in cxl_detach_ep().<br /> <br /> This is easily reproduced with a reload of cxl_acpi in QEMU with CXL<br /> devices present.

Impacto