MOKSHA-2026-0050: LUNperVDI Key Injection via SR.sm_config (dead code)

Advisory IDMOKSHA-2026-0050
GCVE IDGCVE-117-2026-0050
Semantic IDSSMC-5
Published2026-04-24
CVSS 3.12.7 Low
CVSS 3.1 VectorAV:N/AC:L/PR:H/UI:N/S:U/C:N/I:L/A:N
CVSS 4.05.1 Medium
CVSS 4.0 VectorAV:N/AC:L/AT:N/PR:H/UI:N/VC:N/VI:L/VA:N/SC:N/SI:N/SA:N
XAPI ObjectSR
XAPI Fieldsm_config:LUNperVDI
Entry Rolepool-operator
ResearcherJakob Wolffhechel, Moksha

Affected Products

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

Summary

A pool-operator in XAPI-based hypervisors (XenServer, XCP-ng) can inject the LUNperVDI key into SR.sm_config. The key is defined at SR.py:37 and SR._addLUNperVDIkey() exists at SR.py:226, but source analysis confirms _addLUNperVDIkey() is never called by any SM driver and no driver reads sm_config["LUNperVDI"] to decide behavior. The key is an SR-type marker, not a behavioral toggle. Impact is limited to key persistence in the XAPI database without backend consumption. The SR.sm_config field has zero map_keys_roles entries and remains writable after SR creation.

Vulnerability Description

SR.sm_config is a Map(String, String) field writable by pool-operator. The LUNperVDI key was intended to mark whether an SR uses one-LUN-per-VDI mode.

The code path:

  1. SR._addLUNperVDIkey() is defined at SR.py:226 to set sm_config["LUNperVDI"] = "true"
  2. However, _addLUNperVDIkey() is never called by any SM driver in the codebase
  3. No SM driver reads sm_config["LUNperVDI"] to decide behavior
  4. LUNperVDI.py is a separate driver module (used by RawISCSISR and HBASR) - it is the raw-LUN driver itself, not something controlled by the sm_config key
  5. A pool-operator can inject the key: SR.add_to_sm_config(sr, "LUNperVDI", "true")
  6. The key persists in the XAPI database but has no backend effect

The xe CLI rejects sm_config writes with "Map field 'sm-config' is read-only", but direct XenAPI calls (SR.add_to_sm_config, SR.remove_from_sm_config) succeed. The CLI provides a false sense of immutability.

Root Causes

  1. Missing field immutability. SR.sm_config is qualifier:RW despite containing keys that define the SR's storage architecture. The LUNperVDI key is set during SR.create and should be immutable afterward.

  2. Missing RBAC protection. SR.sm_config has zero map_keys_roles entries. The LUNperVDI key inherits the class default _R_POOL_OP.

  3. CLI/API inconsistency. The xe CLI rejects sm_config writes, but the XenAPI accepts them. This creates a false sense of immutability for operators who only use the CLI.

  4. Dead code marker. _addLUNperVDIkey() is defined but never called. The key exists as a vestigial marker with no runtime consumer.

Affected Systems

Directly Affected

Indirectly Affected

Exploitation Scenarios

Scenario Impact Pre-conditions Status
Key injection LUNperVDI=true persists in sm_config pool-operator Source-traced (W)
No backend effect _addLUNperVDIkey() is dead code; no driver reads the key n/a Confirmed via source trace

Chaining Analysis

Detection

Remediation

Short-Term Mitigations

Long-Term Fix

Add map_keys_roles. Protect LUNperVDI at _R_LOCAL_ROOT_ONLY in datamodel.ml. While the key has no backend consumer, the RBAC violation (pool-operator writing driver metadata) remains valid.

Remove dead code. _addLUNperVDIkey() at SR.py:226 is never called and can be safely removed.

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