CVE-2026-31530CWE-416

CVE-2026-31530

High · published April 22, 2026

CVSS v3.1
7.8
EPSS
0%
Percentile
2.0
In the wild
Unconfirmed
What it is

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.

The record
Technical detail
CVSS v3.1
7.8 · HIGH
Vector
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H
CVSS v4.0
Not supplied
EPSS
0.00125 · 2.0th percentile
Weakness
CWE-416 · Use After Free
Published
2026-04-22T18:16Z
Affected products (8)
ProductVersionsFixed in
linux/linux_kernel≥ 6.3, < 6.12.806.12.80
linux/linux_kernel≥ 6.13, < 6.18.216.18.21
linux/linux_kernel≥ 6.19, < 6.19.116.19.11
linux/linux_kernelall versions—
linux/linux_kernelall versions—
linux/linux_kernelall versions—
linux/linux_kernelall versions—
linux/linux_kernelall versions—
References (5)
EPSS history
Timeline
  • 22 APR 13:54Z
    cxl/port: Fix use after free of parent_port in cxl_detach_ep()
    cvelistv5