MOKSHA-2026-0044: QEMU -parallel Path Traversal (VM DoS) via VM.platform

Advisory IDMOKSHA-2026-0044
Semantic IDPLAT-1
Published2026-04-24
CVSS 3.16.5 Medium
CVSS 3.1 VectorAV:N/AC:L/PR:L/UI:N/S:U/C:N/I:N/A:H
CVSS 4.05.3 Medium
CVSS 4.0 VectorAV:N/AC:L/AT:N/PR:L/UI:N/VC:N/VI:N/VA:L/SC:N/SI:N/SA:N
XAPI ObjectVM
XAPI Fieldplatform:parallel
Entry Rolevm-admin
ResearcherJakob Wolffhechel, Moksha

Affected Products

VendorProductVersions
Citrix / Cloud Software GroupXenServer / Citrix Hypervisorall versions (shared XAPI codebase)
VatesXCP-ng8.3.0

Summary

A vm-admin in XAPI-based hypervisors (XenServer, XCP-ng) can prevent a VM from starting by injecting a path traversal payload into VM.platform:parallel. The prefix check in vm_platform.ml:233-242 accepts any string starting with /dev/parport, but path traversal payloads such as /dev/parport../../tmp/marker pass the check and are forwarded to QEMU as the -parallel argument. QEMU's parport chardev backend expects a device node, not a file path - the payload causes QEMU initialization failure (ENOENT), preventing VM startup. No host filesystem read or write capability was confirmed - the impact is limited to VM denial-of-service.

Vulnerability Description

VM.platform is a Map(String, String) field writable by vm-admin with zero map_keys_roles entries. The parallel key controls the QEMU -parallel device argument.

The code path:

  1. vm-admin calls VM.add_to_platform(vm, "parallel", "/dev/parport../../tmp/marker")
  2. At VM start, vm_platform.ml:233-242 validates the value:
    • Accepts "none" or any string starting with /dev/parport
    • The prefix check uses Astring.String.is_prefix ~affix:"/dev/parport" - path traversal passes
  3. Value passes to xenopsd at xenops_server_xen.ml:1945-1946
  4. xenopsd passes it directly to QEMU: -parallel <value> (device.ml:3975-3979)
  5. QEMU attempts to open the path as a parport chardev device
  6. Open fails with ENOENT or "not a valid char driver" - QEMU crashes, VM fails to start

The investigation confirmed that QEMU's -parallel argument uses the parport chardev backend, not the file: backend. Unlike -serial file:path (PLAT-6), this does not create files on the host filesystem. Stock XCP-ng/XenServer disable CONFIG_PARPORT, so /dev/parportN device nodes do not exist even without path traversal.

Root Causes

  1. Insufficient input validation. The prefix check at vm_platform.ml:233-242 accepts any string starting with /dev/parport. It does not reject path traversal sequences (../).

  2. Missing RBAC protection. VM.platform has zero map_keys_roles entries. The parallel key is writable by vm-admin - the lowest delegated management role.

  3. Write-time vs. start-time validation gap. The prefix check occurs at VM start (inside sanity_check), not at write time. An invalid value sits in the database until someone attempts to start the VM.

  4. Missing device node validation. The check verifies a path prefix but does not validate that the path resolves to an actual character device node.

Affected Systems

Directly Affected

Indirectly Affected

Exploitation Scenarios

Scenario Impact Pre-conditions Status
VM startup DoS Target VM cannot start due to QEMU crash on invalid parallel device path vm-admin, target VM Source-traced (investigation #368)
HA restart denial HA-protected VM fails to restart after failover due to corrupted platform key vm-admin, HA-protected target VM Modeled
Persistent DoS The key persists in the database; VM remains unstartable until key is removed vm-admin Source-traced

Chaining Analysis

Detection

Remediation

Short-Term Mitigations

Long-Term Fix

Replace prefix check with exact device whitelist. The sanity_check function should accept only "none" or exact /dev/parportN paths (where N is 0-3). Reject any path containing .. or other traversal sequences.

Add map_keys_roles to VM.platform. Protect the parallel key at _R_POOL_ADMIN in datamodel_vm.ml.

Move validation to write time. Validate platform key values when they are set, not when the VM starts.

Upstream patches exist. They are held privately pending coordinated disclosure.

Disclosure

Disclosure:

References

Credits

Discovered and reported by Jakob Wolffhechel, Moksha.

Jakob Wolffhechel · Moksha · Copenhagen
jakob@wolffhechel.dk · +45 3170 7337
Published 2026-04-24 08:00 CEST · cna.moksha.dk · shittrix.moksha.dk