A vm-admin in XAPI-based hypervisors (XenServer, XCP-ng) can poison VDI.xenstore_data on a source pool, and the poisoned metadata crosses into a target pool when the source host joins the target pool or when VDIs are migrated cross-pool. The pool join code at xapi_pool.ml:1215 copies VDI records including xenstore_data without re-validation. This enables a compromised vm-admin on one pool to inject attacker-controlled storage metadata into a separate, previously uncompromised pool. The field has zero map_keys_roles restrictions, zero write-time validation, and zero cross-pool sanitization.
XAPI pool join operations merge the database of the joining host into the pool master's database. VDI records are copied as part of this process.
The code path at xapi_pool.ml:1215:
~xenstore_data:vdi.API.vDI_xenstore_data
This line copies the joining host's VDI.xenstore_data directly into the target pool's VDI record. No validation, no sanitization, no re-generation from the SM driver.
The attack sequence:
vm-admin poisons VDI.xenstore_data on source pool VDI with attacker-controlled valuesxapi_pool.ml:1215 copies VDI records including poisoned xenstore_data to targetCross-pool migration (SXM - Storage XenMotion) follows a similar pattern: VDI records are recreated on the target pool using metadata from the source, including xenstore_data.
This vector requires pool join or cross-pool migration as a trigger event, making it less immediately exploitable than direct database writes. However, pool joins are a routine operational event in infrastructure lifecycle management (capacity expansion, host replacement, pool consolidation).
No cross-pool sanitization. Pool join copies VDI metadata across pool trust boundaries without any validation or re-generation.
Implicit trust of source pool data. The target pool assumes all metadata from the joining host is legitimate. There is no integrity verification.
Missing RBAC protection. The source pool's vm-admin can poison metadata that will be trusted by the target pool.
No write-time validation. The initial poisoning is possible because the field accepts any key-value pair without validation.
| Scenario | Impact | Pre-conditions | Status |
|---|---|---|---|
| Pool join contamination | Target pool receives VDIs with poisoned xenstore_data | vm-admin on source, pool join event | Source-traced |
| Cross-pool migration contamination | Migrated VDI carries poisoned metadata to target | vm-admin on source, SXM migration | Source-traced |
| Trust boundary violation | Attacker on one pool injects data into another pool's database | vm-admin on source, pool merge | Source-traced |
| Persistent contamination | Poisoned data persists on target pool after source host is removed | vm-admin on source, pool join then eject | Source-traced |
xenstore_data after pool join operations for unexpected entriesdisclosure/vendor-detection-guidance.mdRe-generate xenstore_data on pool join. Instead of copying the source pool's database field, query the SM driver on the target pool for fresh metadata after the VDI's storage is available.
Add cross-pool validation. Validate xenstore_data entries against a whitelist of SM-known keys during pool join. Reject or strip unknown keys.
Restrict write access. Change the field write role to _R_POOL_ADMIN to prevent vm-admin from poisoning the source data in the first place.
Upstream patches exist. They are held privately pending coordinated disclosure.
Disclosure:
xapi_pool.ml:1215 (pool join copies xenstore_data across pool boundary), datamodel.ml:6352-6369 (field definition, no map_keys_roles), xapi_vdi.ml:792 (VDI.introduce/db_introduce stores xenstore_data)disclosure/advisories/vxd-security-advisory.md (VXD-4)research/investigations/vdi-xenstore-data.mdDiscovered and reported by Jakob Wolffhechel, Moksha.