utmapp / utmapp/UTM

guest VM can crash UTM host process via QEMU Guest Agent (deterministic DoS)

Open
#7,684 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
Swift
Stars
35.5k
Forks
1.8k
Avg merge
5d 5h
Merged PRs (30d)
7

Description

**Security issue: guest VM can crash UTM host process via QEMU Guest Agent (deterministic DoS)**

A guest with root access can crash the UTM host process instantly with a single JSON message sent over the QEMU Guest Agent virtio channel. All running VMs are terminated as a result.

**Root cause**

`QEMUManager.receivedDictionary:` processes any `"event"` key received from the guest without validating that the Guest Agent protocol permits guest-originated events. It dispatches the value to `qapi_event_dispatch()`, which calls `qapi_enum_parse()` with `&error_abort`. Any unknown event name triggers `error_handle_fatal()` → `abort()`, crashing the UTM process immediately.

The QEMU Guest Agent protocol does not define any guest-originated events — this code path should never be reachable from guest input.

**Affected versions**

UTM 4.7.5 (118), QEMU backend, any Linux guest with root access.

**Configuration**

- UTM Version: 4.7.5 (118)
- macOS Version: Tahoe 26.4 (25E246)
- Mac Chip: M2 Pro
- Guest: Ubuntu 24.04 LTS ARM64, QEMU backend

**Reproduction**

From inside the guest VM with root access:

```python
import json, time

with open('/dev/virtio-ports/org.qemu.guest_agent.0', 'wb', buffering=0) as port:
time.sleep(1) # wait for UTM handshake
payload = b'\xff' + json.dumps({"event": "X"}).encode() + b'\n'
port.write(payload)
```

UTM crashes within 1 second. Reproduced 2/2 times on a fresh UTM instance (uptime: 90 seconds at crash).

**Suggested fix**

Option A — filter `"event"` keys in `QEMUGuestAgent` before dispatch (guest agent protocol defines no guest-originated events).

Option B — replace `&error_abort` with a recoverable error pointer in `qapi_event_dispatch()`:

```c
Error *err = NULL;
num = qapi_enum_parse(&QAPIEvent_lookup, event, -1, &err);
if (num < 0) { error_free(err); return; }
```

**Crash logs attached** — two separate UTM instances, identical backtrace, same 7 UTM offsets (+4479416, +4471664, +4471292, +4471380, +4472232, +4375344, [+4458512).[](url)](url)

[bug UTM.rtf](https://github.com/user-attachments/files/26747211/bug.UTM.rtf)

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.