# QEMU CXL Guest-to-Host Code Execution Vulnerability: Technical Analysis of the Type-3 Mailbox Escape

> Uncover the QEMU CXL guest-to-host code execution vulnerability. Learn how two flaws in mailbox command handlers allow VM guests to run arbitrary commands on the host.

- Repository: [bikini/exploitarium](https://github.com/bikini/exploitarium)
- Tags: technical-analysis
- Published: 2026-09-07

---

**The QEMU CXL guest-to-host code execution vulnerability is a critical escape primitive in QEMU's CXL Type-3 implementation that allows unprivileged virtual machine guests to execute arbitrary commands on the host system by exploiting two flaws in mailbox command handlers.**

This vulnerability, documented in the `bikini/exploitarium` repository, demonstrates how improper bounds checking in CXL (Compute Express Link) mailbox commands creates a complete guest-to-host escape chain. The exploit targets QEMU's emulation of CXL Type-3 devices, specifically abusing the `GET_LOG` and `SET_FEATURE` command handlers to leak memory addresses and forge internal QEMU object structures.

## Root Cause: Twin Flaws in CXL Mailbox Handling

The vulnerability stems from two distinct memory safety issues in QEMU's CXL Type-3 mailbox implementation. Together, these flaws enable an attacker to first leak critical memory addresses and then overwrite vital structures to hijack control flow.

### GET_LOG Off-by-One Out-of-Bounds Read

The `GET_LOG` mailbox command handler contains an **off-by-one validation error** in its bounds checking logic. According to the source analysis in the `bikini/exploitarium` repository, the handler validates that `offset + length` remains within the bounds of the internal log buffer size, but subsequently uses the raw `offset` value directly as an array index when copying data to the guest.

This validation gap allows a guest-controlled offset to read past the end of the `cci->cel_log` buffer. By carefully selecting the offset parameter, an attacker can leak a pointer to QEMU's text (PIE) segment and obtain the address of the host's `CXLType3Dev` object, defeating Address Space Layout Randomization (ASLR) and locating the target structure for the next phase of the attack.

### SET_FEATURE Rank-Sparing Unbounded Write

The second flaw resides in the `SET_FEATURE` command handler for the **rank-sparing** feature. This handler copies guest-supplied data into `rank_sparing_wr_attrs + hdr->offset` without performing any bounds check on the destination object size or the offset value.

Because `rank_sparing_wr_attrs` resides within the `CXLType3Dev` structure, supplying a large `hdr->offset` value allows an attacker to write beyond the intended buffer and overwrite the tail of the `CXLType3Dev` object. This capability enables the forging of a complete hierarchy of QEMU internal objects including `FlatView`, `AddressSpaceDispatch`, `MemoryRegionSection`, `MemoryRegion`, and critically, `MemoryRegionOps`. By forging the `MemoryRegionOps.write` callback to point to the host's `system()` function, the attacker establishes a direct path to arbitrary code execution.

## Exploitation Chain: From Guest to Host

The complete exploitation flow implemented in [`stage2.c`](https://github.com/bikini/exploitarium/blob/main/stage2.c) and `boot.asm` proceeds through six distinct phases to achieve host code execution:

1. **Initial Setup**: The guest bootloader (16-bit assembly from `boot.asm`) loads a protected-mode payload ([`stage2.c`](https://github.com/bikini/exploitarium/blob/main/stage2.c)), which configures the PCI-CXL root port and Type-3 endpoint via PCI configuration I/O operations.

2. **Information Disclosure**: The guest issues a `GET_LOG` request with a crafted offset to trigger the out-of-bounds read, leaking the QEMU PIE base address and a pointer to the `CXLType3Dev` object (`ct3d`).

3. **Symbol Resolution**: Using the leaked PIE base, the payload computes the runtime address of `memmove@plt` and other libc symbols, ultimately locating the address of the `system()` function.

4. **Structure Forging**: The guest sends a `SET_FEATURE` request that writes a forged dynamic-capacity state into the tail of the `CXLType3Dev` object. This injects a fake `MemoryRegionOps` structure with a `write` callback pointing to the resolved `system()` address.

5. **Trigger Execution**: A subsequent CXL media operation invokes the forged `MemoryRegionOps.write` callback, which executes the attacker-controlled command on the host.

6. **Verification**: Successful exploitation creates the file `/tmp/qemu_cxl_escape_marker` on the host filesystem, demonstrating that code execution occurred inside the QEMU process with the same privileges as the host user.

## Reproducing the Vulnerability

The `bikini/exploitarium` repository provides a complete proof-of-concept that automates this exploit chain. To reproduce the vulnerability against a QEMU binary built with CXL Type-3 support:

```bash

# From the PoC directory, execute the run script with the path to your QEMU binary

sh run.sh /absolute/path/to/qemu-system-x86_64

```

Upon successful execution, the serial output will display leaked addresses and the final system call invocation:

```

stage2 start
pci done
handler=0x00005d41f6d636f0
qemu_base=0x00005d41f68b6000
ct3d=0x000077f609b3a010
rank=0x000077f60a1ffb7a
fake leak call
media-op sent
...
system=0x000077f60c858750
fake system call
stage2 done

```

The presence of `/tmp/qemu_cxl_escape_marker` on the host confirms successful code execution.

### Building from Source

To recreate the BIOS floppy image from the assembly and C source:

```bash

# Rebuild poc.img from boot.asm and stage2.c

sh build.sh

```

The core exploit logic in [`stage2.c`](https://github.com/bikini/exploitarium/blob/main/stage2.c) performs the critical mailbox operations:

```c
/* Leak a QEMU pointer via crafted GET_LOG request */
w32(MBOX_PAYLOAD + 8, CXL_STATIC_VMEM_SIZE);   // length parameter
w32(MBOX_PAYLOAD + 16, CXL_CACHELINE_SIZE);   // malicious offset triggers OOB read

/* Forge fake MemoryRegionOps.write callback via SET_FEATURE */
memcpy((uint8_t *)&ct3d->rank_sparing_wr_attrs + hdr->offset,
       forged_memory_region_ops, sizeof(forged_memory_region_ops));

```

## Summary

- The **QEMU CXL guest-to-host code execution vulnerability** combines an off-by-one read in `GET_LOG` with an unbounded write in `SET_FEATURE` to escape virtualization boundaries.
- The `GET_LOG` flaw leaks the QEMU PIE base and `CXLType3Dev` object location, bypassing ASLR protections.
- The `SET_FEATURE` rank-sparing handler allows writing beyond `rank_sparing_wr_attrs` to forge `MemoryRegionOps` structures and hijack callback execution.
- Exploitation requires no host privileges—only the ability to run a guest VM with CXL Type-3 device emulation enabled.
- The `bikini/exploitarium` PoC demonstrates full exploitation via custom 16-bit bootloader and 32-bit stage2 payload.

## Frequently Asked Questions

### How does the GET_LOG vulnerability leak memory addresses?

The `GET_LOG` command handler validates that `offset + length` fits within the log buffer but then accesses `cci->cel_log[offset]` directly. By supplying an offset that passes the sum check but exceeds the buffer boundary, a guest can read memory contents beyond the allocated buffer. This leaks pointers to QEMU's code segment and the `CXLType3Dev` object instance, providing the necessary addresses to calculate the location of libc functions like `system()`.

### What QEMU components are affected by the SET_FEATURE vulnerability?

The vulnerability specifically affects the **CXL Type-3 device emulation** code in QEMU, particularly the mailbox command handler for the rank-sparing feature. The `SET_FEATURE` command writes to the `rank_sparing_wr_attrs` field within the `CXLType3Dev` structure. Because this field is embedded early in the structure, an unchecked offset allows overwriting adjacent fields including the dynamic capacity state and memory region structures.

### Does this vulnerability require special guest privileges?

No. The exploit chain operates from a **fully unprivileged guest context**. The guest only needs to issue standard CXL mailbox commands through the emulated PCI device interface. Neither root access within the guest nor special QEMU monitor permissions are required, as the vulnerability exists in the device emulation layer that processes guest-initiated mailbox requests.

### How can I verify if my QEMU installation is vulnerable?

Check if your QEMU build includes CXL Type-3 device support by verifying the presence of CXL-related device options. The vulnerability affects versions implementing the `GET_LOG` and `SET_FEATURE` mailbox commands without proper bounds validation on the `offset` parameter. Running the `bikini/exploitarium` PoC against your QEMU binary and observing the creation of `/tmp/qemu_cxl_escape_marker` confirms exploitability.