QEMU CXL Escape

somebudyelse1 pts0 comments

pocs/qemu/README.md at main · v12-security/pocs · GitHub

//blob/show" data-turbo-transient="true" />

Skip to content

Search or jump to...

Search code, repositories, users, issues, pull requests...

-->

Search

Clear

Search syntax tips

Provide feedback

--><br>We read every piece of feedback, and take your input very seriously.

Include my email address so I can be contacted

Cancel

Submit feedback

Saved searches

Use saved searches to filter your results more quickly

-->

Name

Query

To see all available qualifiers, see our documentation.

Cancel

Create saved search

Sign in

//blob/show;ref_cta:Sign up;ref_loc:header logged out"}"<br>Sign up

Appearance settings

Resetting focus

You signed in with another tab or window. Reload to refresh your session.<br>You signed out in another tab or window. Reload to refresh your session.<br>You switched accounts on another tab or window. Reload to refresh your session.

Dismiss alert

{{ message }}

v12-security

pocs

Public

Notifications<br>You must be signed in to change notification settings

Fork<br>75

Star<br>388

FilesExpand file tree

main

/README.md

Copy path

Blame<br>More file actions

Blame<br>More file actions

Latest commit

History<br>History<br>History

133 lines (92 loc) · 4.75 KB

main

/README.md

Top

File metadata and controls<br>Preview

Code

Blame

133 lines (92 loc) · 4.75 KB

Raw<br>Copy raw file<br>Download raw file

OutlineEdit and raw actions

QEMUtiny

qemu.mp4

Abstract

QEMUtiny is a memory corruption vulnerability in QEMU's implementation of CXL Type-3<br>device emulation, reported against QEMU master 007b29752e and confirmed<br>working against 5e61afe (May 11, 2026).

QEMUtiny was discovered autonomously with V12 by Aaron Esau of the<br>V12 security team.

Want to find issues like this in your own code? Try V12 at v12.sh.

The PoC chains two CXL mailbox bugs in hw/cxl/cxl-mailbox-utils.c: an<br>out-of-bounds read in GET_LOG, followed by an out-of-bounds write in<br>SET_FEATURE.

OOB read: cmd_logs_get_log() treats the CEL log offset as an array<br>index in the memmove() source expression even though the CXL mailbox<br>offset is in bytes.

OOB write: cmd_features_set_feature() accepts byte offsets into<br>several small feature write-attribute structures without checking that<br>offset + bytes_to_copy stays inside the selected structure.

We reported the bugs upstream. Maintainers state CXL support is currently for at non-virtualization use cases, so we feel comfortable release the PoC publicly.

The included poc.c is a working exploit that drives the emulated CXL mailbox from the guest through the device BAR. It depends on offsets for the specific QEMU build and host libc layout.<br>The exploit can be weaponized to work reliably across many QEMU versions using the OOB read to scan memory. However this is out of scope for this PoC.

"QEMUtiny"?

QEMU + Mutiny.

Building

gcc -O2 -Wall -Wextra -o exp poc.c

The reproducer must be run as root inside the guest because it writes PCI config<br>space and mmaps the CXL device BAR through sysfs.

sudo ./exp

One-line version:

git clone https://github.com/v12-security/pocs.git && cd pocs/qemu && gcc -O2 -Wall -Wextra -o exp poc.c && sudo ./exp

Test Setup

Use ./run_qemu_shell.sh. Then in the guest, use /exp

poc.c assumes the CXL Type-3 device appears in the guest at:

/sys/bus/pci/devices/0000:35:00.0

and that BAR2 is exposed as:

/sys/bus/pci/devices/0000:35:00.0/resource2

If your guest enumerates the device at a different BDF, update the two sysfs<br>paths in main().

How It Works

Mailbox access. The guest enables PCI memory decoding for the CXL device,<br>maps BAR2, and sends CXL mailbox commands by writing the mailbox payload,<br>command, and control registers directly.

CEL out-of-bounds read. cmd_logs_get_log() checks the requested CEL<br>range as if offset were a byte offset, but then performs pointer arithmetic<br>on cci->cel_log as a struct cel_log *. poc.c uses<br>GET_LOG_OOB_BASE_OFFSET to land just past the CEL buffer and read adjacent<br>QEMU CXL state.

QEMU address discovery. The out-of-bounds CEL read leaks a CXL mailbox<br>command handler pointer and the CXLType3Dev heap address. The handler<br>pointer gives the QEMU PIE base for this build.

Rank sparing overflow. The demo sends SET_FEATURE / RANK_SPARING with<br>a non-zero feature offset and a large payload. The rank sparing case copies<br>into ct3d->rank_sparing_wr_attrs + hdr->offset without bounding the copy to<br>sizeof(ct3d->rank_sparing_wr_attrs), so the payload continues into later<br>CXLType3Dev fields.

Fake memory dispatch state. The overflowed payload plants enough fake<br>FlatView, dispatch, section, MemoryRegion, and MemoryRegionOps state<br>for the sanitize path to call a controlled MemoryRegionOps.write callback.

Callback trigger. MEDIA_OPERATIONS / SANITIZE starts a background<br>operation. When the sanitize worker reaches address_space_set(), it walks<br>the corrupted dispatch state and invokes the forged write callback. The demo<br>first uses this to call memmove() and leak libc, then repoints the callback<br>to...

qemu mailbox read offset file device

Related Articles