CVE-2026-31530

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

Configuration 1 (hide)

OR cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*
cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*
cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*
cpe:2.3:o:linux:linux_kernel:7.0:rc1:*:*:*:*:*:*
cpe:2.3:o:linux:linux_kernel:7.0:rc2:*:*:*:*:*:*
cpe:2.3:o:linux:linux_kernel:7.0:rc3:*:*:*:*:*:*
cpe:2.3:o:linux:linux_kernel:7.0:rc4:*:*:*:*:*:*
cpe:2.3:o:linux:linux_kernel:7.0:rc5:*:*:*:*:*:*

History

11 Nov 2026, 23:10

Type Values Removed Values Added
Summary
  • (es) En el kernel de Linux, la siguiente vulnerabilidad ha sido resuelta: cxl/port: Corrección de uso después de liberación de parent_port en cxl_detach_ep() cxl_detach_ep() es llamada durante la eliminación de abajo hacia arriba cuando todos los dispositivos de memoria CXL debajo de un puerto de switch han sido eliminados. Para cada puerto en la jerarquía, bloquea tanto el puerto como su padre, elimina el punto final, y si el puerto ahora está vacío, lo marca como muerto y anula el registro del puerto llamando a delete_switch_port(). Hay dos lugares durante este trabajo donde parent_port puede ser usado después de su liberación: Primero, una desconexión concurrente puede haber procesado ya un puerto para cuando un segundo trabajador lo encuentra a través de bus_find_device(). Sin fijar parent_port, puede que ya esté liberado cuando descubrimos port -> dead e intentamos desbloquear parent_port. En un kernel de producción eso es una corrupción de memoria silenciosa, con depuración de bloqueo, se ve así: DEBUG_LOCKS_WARN_ON(__owner_task(owner) != get_current()) WARNING: kernel/locking/mutex.c:949 at __mutex_unlock_slowpath+0x1ee/0x310 Traza de Llamada: mutex_unlock+0xd/0x20 cxl_detach_ep+0x180/0x400 [cxl_core] devm_action_release+0x10/0x20 devres_release_all+0xa8/0xe0 device_unbind_cleanup+0xd/0xa0 really_probe+0x1a6/0x3e0 Segundo, delete_switch_port() libera tres acciones devm registradas contra parent_port. La última de ellas es unregister_port() y llama a device_unregister() en el puerto hijo, lo que puede generar una cascada. Si parent_port ahora también está vacío el núcleo del dispositivo puede anular su registro y liberarlo también. Así que para cuando delete_switch_port() regresa, parent_port puede estar libre, y el subsiguiente device_unlock(ref:parent_port -> dev) opera sobre memoria liberada. El registro del kernel se ve igual que el anterior, con un desplazamiento diferente en cxl_detach_ep(). Ambos de estos problemas provienen de la ausencia de una garantía de vida útil entre un puerto hijo y su puerto padre. Establecer una regla de vida útil para los puertos: los puertos hijos mantienen una referencia a su dispositivo padre hasta su liberación. Tomar la referencia cuando el puerto es asignado y soltarla cuando es liberado. Esto asegura que el padre sea válido durante toda la vida útil del hijo y elimina la ventana de uso después de liberación en cxl_detach_ep(). Esto se reproduce fácilmente con una recarga de cxl_acpi en QEMU con dispositivos CXL presentes.

21 Oct 2026, 13:18

Type Values Removed Values Added
References
  • () https://git.kernel.org/stable/c/b1f62588ab1be6c9535d74348003c86b47ec4abd -

Information

Published : 2026-04-22 14:16

Updated : 2026-11-11 23:10


NVD link : CVE-2026-31530

Mitre link : CVE-2026-31530

CVE.ORG link : CVE-2026-31530


JSON object : View

Products Affected

linux

  • linux_kernel
CWE
CWE-416

Use After Free