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->dead and<br />
attempt to unlock the parent_port. In a production kernel that&#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(&parent_port->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.



