A user with the vm-admin role can write arbitrary host filesystem files by setting VM.platform:hvm_serial to file:<path>. XAPI reads this key from the raw database record (bypassing the filtered_flags allowlist) and passes it to QEMU as the -serial argument. QEMU creates the target file on the host filesystem even if the VM fails to fully start. This is an independent host filesystem write primitive that chains into all 34 FIST debug points in XAPI without requiring BOC-1. The file is created with root ownership because QEMU runs as root in dom0.
VM.platform is a Map(String, String) field controlling hypervisor-level VM configuration. The hvm_serial key specifies the QEMU serial device. XAPI reads this key at xapi_xenops.ml:456 from the raw vm.API.vM_platform database value - not from the filtered platformdata that passes through sanity_check.
XAPI applies a filtered_flags allowlist to VM.platform before passing values to xenopsd. This allowlist blocks unrecognized keys from reaching the QEMU command line. However, hvm_serial is read independently from the raw database record at line 456, completely bypassing the allowlist:
1. hvm_serial is NOT in filtered_flags
2. filtered_flags prevents it from reaching platformdata
3. BUT xapi_xenops.ml:456 reads it from raw vm.API.vM_platform
4. The value is passed directly to xenopsd as the serial field in HVM info
5. xenopsd passes it verbatim to QEMU: -serial file:<path>
QEMU creates the file specified in the -serial file:<path> argument during its own initialization, before the VM domain is fully created. If domain creation fails for any reason, the file still exists. This means:
VM.add_to_platform + VM.start (which can fail)[root@xcpng ~]# /usr/lib64/xen/bin/qemu-system-i386 -accel xen \
-serial "file:/tmp/test-serial-qemu-check" -M none
[root@xcpng ~]# ls -la /tmp/test-serial-qemu-check
-rw-r--r-- 1 root root 0 Feb 7 14:01 /tmp/test-serial-qemu-check
Confirmed on the live production host: QEMU creates the file as root.
filtered_flags bypass. hvm_serial is read from the raw database record, not from the filtered platformdata. The allowlist provides zero protection for this key.
Missing per-key RBAC. VM.platform has zero map_keys_roles entries. All keys are writable by vm-admin.
No write-time validation. All VM.platform validation occurs at VM start time (sanity_check), not at write time. The malicious value persists in the database.
QEMU file creation at init. QEMU creates the serial output file during its own initialization before checking whether the VM domain is viable. This guarantees file creation regardless of VM start success.
| Scenario | Impact | Pre-conditions | Status |
|---|---|---|---|
| FIST point activation | Create /tmp/fist_disable_memory_checks, /tmp/fist_disable_ha, etc. - disables XAPI internal safety checks |
None | Confirmed (live host file creation verified) |
| Arbitrary file creation | Create files in any root-writable directory | None | Confirmed (QEMU runs as root in dom0) |
| PLAT-6 + FIST chain | Disable HA fencing → split-brain vulnerability; disable memory checks → overcommitment | Chains with 34 FIST debug points | Modeled (live file creation confirmed, FIST effects documented) |
| No-boot exploitation | File created even when VM start fails | Deliberately misconfigured VM | Confirmed (QEMU creates file during init, before domain creation) |
| File | Effect |
|---|---|
/tmp/fist_disable_memory_checks |
Disables XAPI memory validation |
/tmp/fist_disable_ha |
Disables HA fencing |
/tmp/fist_pause_storage_migrate |
Pauses storage migration (DoS) |
/tmp/fist_disable_sched_gran_affinity_check |
Disables CPU scheduling granularity checks |
There are 34 FIST points in XAPI, each controllable via this primitive.
-serial file: with paths outside /dev//tmp/fist_* files on all hosts - these should not exist in productionVM.platform:hvm_serial set to any value containing file:disclosure/vendor-detection-guidance.mdVM.platform entries for hvm_serial containing file: prefix/tmp/fist_* files from all hostsValidate hvm_serial. Restrict the hvm_serial value to known safe serial device types. Reject file: prefix entirely - there is no legitimate use case for QEMU serial output to host filesystem in production.
Add map_keys_roles. Add per-key RBAC for hvm_serial requiring _R_POOL_ADMIN in datamodel.ml.
Fix the filtered_flags bypass. Read hvm_serial from filtered platformdata, not from the raw database value. This ensures the allowlist is applied consistently.
Add write-time validation. Validate platform key values when they are set, not just at VM start.
Upstream patches exist. They are held privately pending coordinated disclosure.
Disclosure:
xapi_xenops.ml:456 (hvm_serial read from raw platform), vm_platform.ml (sanity_check / filtered_flags), xenops_server_xen.ml (QEMU command line construction)disclosure/advisories/plat-security-advisory.md (PLAT-6)research/investigations/vm-platform.md10.20.30.102 confirmed file creation via QEMU -serial file: argumentDiscovered and reported by Jakob Wolffhechel, Moksha.