A pool-operator in XAPI-based hypervisors (XenServer, XCP-ng) can inject a fake rolling upgrade state by writing the rolling_upgrade_in_progress key to Pool.other_config. The mere presence of this key - regardless of value - causes helpers.ml:718-719 to return true, disabling version compatibility checks, altering pool behavior during operations, and preventing detection of version mismatches across the pool. The key has no map_keys_roles protection and no write-time validation, and with BOC-1 chaining, a vm-admin can reach this vector via RBAC collapse.
Pool.other_config is a Map(String, String) field writable by pool-operator. The rolling_upgrade_in_progress key controls whether the pool operates in rolling upgrade mode - a transient state intended for use only during actual version upgrades.
The code path:
pool-operator calls Pool.add_to_other_config(pool, "rolling_upgrade_in_progress", "") (any value works)helpers.ml:718-719 checks List.mem_assoc "rolling_upgrade_in_progress" - a pure presence checktrue regardless of the key's valuedb_gc.ml:161-163 - triggers rolling upgrade resynchronizationxapi_host_helpers.ml:624-625 - disables software version checking during pool joinxapi-autostart-vms script - suppresses VM auto-startNo validation occurs at write time. The key is not protected by map_keys_roles. The Pool.other_config field only protects UI keys (folder, XenCenter.CustomFields.*, EMPTY_FOLDERS) at _R_VM_OP.
Missing RBAC protection. Pool.other_config has zero map_keys_roles entries for infrastructure keys. The rolling_upgrade_in_progress key inherits the class default _R_POOL_OP.
Presence-only check. The consumer at helpers.ml:718-719 uses List.mem_assoc - the key's mere existence triggers upgrade mode. There is no validation of expected values, no cross-check against actual upgrade state, and no timestamp or session binding.
Missing write-time validation. No mechanism verifies that a rolling upgrade is actually in progress before accepting this key.
Insufficient logging. No security-level log event is generated when this key is written.
| Scenario | Impact | Pre-conditions | Status |
|---|---|---|---|
| Fake upgrade mode | Disables version compatibility checks, allows mismatched hosts to join pool | pool-operator | Source-traced |
| VM auto-start suppression | VMs fail to auto-start after host reboot during fake upgrade state | pool-operator | Source-traced |
| BOC-1 chain | vm-admin uses BOC-1 S3 to self-grant pool-operator, then injects fake upgrade state | vm-admin, BOC-1 | Source-traced |
rolling_upgrade_in_progress key to disable version checks across the pool. Effective minimum role with BOC-1: vm-admin.Pool.other_config for the rolling_upgrade_in_progress key outside of actual upgrade operationsdisclosure/vendor-detection-guidance.mdPool.other_config for unexpected rolling_upgrade_in_progress keysProtect the key via map_keys_roles. Add rolling_upgrade_in_progress to Pool.other_config map_keys_roles at _R_LOCAL_ROOT_ONLY or _R_POOL_ADMIN in datamodel_pool.ml. This key should only be set by internal XAPI upgrade orchestration, not by API users.
Add state validation. The consumer at helpers.ml:718-719 should cross-check against actual upgrade state (e.g., verify that an RPU task exists) rather than relying solely on a user-writable key.
Upstream patches exist. They are held privately pending coordinated disclosure.
Disclosure:
helpers.ml:718-719 (presence check), db_gc.ml:161-163 (resynchronization consumer), xapi_host_helpers.ml:624-625 (version check bypass), datamodel_pool.ml:1764-1773 (field definition)disclosure/advisories/ploc-security-advisory.md (PLOC-1)research/investigations/pool-other-config.mdDiscovered and reported by Jakob Wolffhechel, Moksha.