MOKSHA-2026-0039: Filesystem Layout Manipulation via SR.sm_config nosubdir/subdir

Advisory IDMOKSHA-2026-0039
Semantic IDSSMC-4
Published2026-04-24
CVSS 3.16.5 Medium
CVSS 3.1 VectorAV:N/AC:L/PR:H/UI:N/S:U/C:N/I:N/A:H
CVSS 4.07.0 High
CVSS 4.0 VectorAV:N/AC:L/AT:N/PR:H/UI:N/VC:N/VI:H/VA:L/SC:N/SI:L/SA:N
XAPI ObjectSR
XAPI Fieldsm_config:nosubdir
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 manipulate the filesystem layout of NFS and MooseFS storage repositories by modifying the nosubdir or subdir key in SR.sm_config after SR creation. Changing nosubdir from false to true (or vice versa) on an NFS SR causes the driver to look for VDIs in the wrong directory. All VDIs appear to not exist, causing VM boot failures and complete data inaccessibility. The attack is reversible by restoring the correct value but causes service disruption for all VMs on the affected SR. The sm_config field has zero map_keys_roles entries, and these keys are intended to be set once during SR.create but remain writable.

Vulnerability Description

SR.sm_config is a Map(String, String) field writable by pool-operator. The nosubdir key (NFS) and subdir key (MooseFS) control whether the SR driver stores VDIs in a per-SR subdirectory on the remote filesystem or in the root of the shared export.

The code path:

  1. During SR.create, the SM driver sets sm_config:nosubdir based on the creation parameters
  2. NFSSR.__init__() reads self.nosubdir = self.sm_config.get('nosubdir') == "true" (NFSSR.py:95)
  3. Path construction uses the flag: not self.nosubdir and sr_uuid or "" (NFSSR.py:100)
  4. A pool-operator changes nosubdir from "false" to "true" (or vice versa)
  5. On next SR scan or VDI operation, the driver constructs paths pointing to the wrong location
  6. VDI files are not found at the expected path - all VDIs appear missing

For NFS SRs:

Flipping this flag causes the driver to look for VDIs in the wrong directory. The VDI files still exist on disk but are invisible to the driver.

The same pattern applies to MooseFS SRs via the subdir key (MooseFSSR.py).

Root Causes

  1. Missing field immutability. SR.sm_config is qualifier:RW despite containing keys that define the SR's physical layout and should be immutable after creation.

  2. Missing RBAC protection. SR.sm_config has zero map_keys_roles entries. The nosubdir and subdir keys inherit the class default _R_POOL_OP.

  3. No consistency check. The driver does not verify that VDI files exist at the computed path before reporting them as missing. A simple existence check at the alternate location would detect the misconfiguration.

  4. Mutable layout metadata. The physical layout of an SR (subdirectory vs. root) is a creation-time decision. Storing it in a mutable field allows post-creation corruption.

Affected Systems

Directly Affected

Indirectly Affected

Exploitation Scenarios

Scenario Impact Pre-conditions Status
NFS layout flip All VDIs on NFS SR appear missing, VM boot failures pool-operator, NFS SR Source-traced
MooseFS layout flip All VDIs on MooseFS SR appear missing pool-operator, MooseFS SR Source-traced
Service disruption All VMs on affected SR fail to boot or experience I/O errors pool-operator, NFS/MooseFS SR with running VMs Modeled
BOC-1 chain vm-admin uses BOC-1 S3 to self-grant pool-operator, then flips layout flag vm-admin, BOC-1 + NFS SR Source-traced

Detection

Remediation

Short-Term Mitigations

Long-Term Fix

Enforce sm_config immutability. Driver-set keys like nosubdir and subdir should be immutable after SR.create. Implement a write-once mechanism for layout-defining keys.

Add map_keys_roles. Protect nosubdir and subdir at _R_LOCAL_ROOT_ONLY in datamodel.ml.

Add consistency verification. When a VDI scan finds no VDIs at the expected path, check the alternate path (with/without subdirectory) and log a warning if VDIs exist at the alternate location.

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