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...