5.3.1 The Layer Model

A layer is a named collection of registry writes that can be managed as a unit. Layers have precedence, and the highest-precedence entry wins. They are how role installation, Group Policy and configuration revert all work, and they are the reason removing a role does not leave its settings behind.

FieldMutableDescription
NameNoThe layer's identity — not a GUID, not an integer. Case-preserving, compared with Unicode Simple Case Folding. Bounded by MaxPathComponentLength.
PrecedenceYesHigher wins. Default 0.
EnabledYesA disabled layer is invisible during resolution unless it is attached to the resolving thread's credentials (§5.3.5). Default true.
OwnerThe SID of the principal that created the layer. Informational only.

The name being the identity is deliberate. Layer names are code-generated and meaningful by construction — role-jellyfin, gpo-security-baseline — so there is nothing an opaque identifier would add.

Owner is never used for an access check; authorisation is the descriptor on the layer's metadata key (§5.3.4). It is also not quite immutable as a field: a refresh re-reads the Owner value and re-selects it, so rewriting the value does change what is cached. Because nothing consults it, that has no effect on anything.

5.3.1.1 Precedence tiers #

The base layer and role layers all sit at precedence 0. Within one tier, the most recent write wins — the highest sequence number. Group Policy layers sit above 0 and override both.

Establishing or raising a layer's precedence above 0 requires SeTcbPrivilege (§5.3.4). That is what keeps the tier boundary meaningful.

5.3.1.2 Caps #

MaxTotalLayers, default 1024, bounds the in-memory layer table. Creating a layer when it is full returns ENOSPC.

The table itself is a fixed array sized at compile time for 1023 dynamic layers plus the base layer. MaxTotalLayers is configurable up to 65536, and a value above 1024 validates and publishes, but the table still runs out at 1023 dynamic entries. Values below 1024 bind correctly.

MaxLayersPerValue, default 128, bounds how many layers may write to the same (key GUID, value name) pair. It is a guard against amplification — every read of that value has to resolve every entry — not an access control boundary.

It is enforced at REG_IOC_SET_VALUE time, before the source is contacted, by querying the source for the current entry count. A write that replaces an existing entry in the same layer does not increase the count and is not checked. Exceeding the cap is ENOSPC.

The check is deliberately best-effort admission control, not a storage invariant. It queries and then dispatches without holding anything, so concurrent writers can both observe room and both proceed. Sources are not required to enforce it atomically. Once LCS observes a count at or above the cap, further new-layer writes are refused.

Blanket tombstones and value deletions are not subject to it.

5.3.1.3 Layers are global; entries are per-source #

There is one authoritative layer table, held by the kernel. Each source stores layer entries — path entries and value writes tagged with layer name strings — for its own hives. Layer metadata is global and lives in one place.

A source never needs the layer table. It stores what it is told, tagged with whatever name it is given, and returns everything on request. A source that has never seen a particular layer name simply stores entries carrying it. Resolution — precedence, enabled state, tombstone evaluation — happens entirely in the kernel, and the layer snapshot is passed into each operation rather than pushed to sources. There is no RSI operation that hands a source the layer list.

Edit this page