# 5.6 SD Inheritance

_Peios / Advanced Peios / PCDS / Security Descriptor_

> How inheritable ACEs propagate from a container to a new child — the inheritance flags, CREATOR OWNER and CREATOR GROUP substitution, and the algorithm itself.

Security Descriptors propagate structurally. When a file is created in a
directory, the directory's inheritable ACEs flow down to the new file's
SD. This automatic propagation is inheritance.

Inheritance applies to objects with a container/child relationship:
directories contain files and subdirectories, registry keys contain
subkeys and values. Objects without a container parent (standalone IPC
endpoints, tokens, processes) do not inherit.

## 5.6.1 Inheritance flags

Four flags in the ACE header's AceFlags field control propagation:

| Flag | Value | Description |
|---|---|---|
| OBJECT_INHERIT_ACE (OI) | 0x01 | Inherited by non-container children (files). For container children (subdirectories), inherited as inherit-only unless NP is also set. |
| CONTAINER_INHERIT_ACE (CI) | 0x02 | Inherited by container children (subdirectories). The inherited ACE remains inheritable (propagates to grandchildren) unless NP is also set. |
| NO_PROPAGATE_INHERIT_ACE (NP) | 0x04 | When inherited, OI and CI flags are cleared on the copy. One-level inheritance. |
| INHERIT_ONLY_ACE (IO) | 0x08 | Does not apply to the object it is attached to. Exists only to be inherited by children. |

A fifth flag records provenance:

| Flag | Value | Description |
|---|---|---|
| INHERITED_ACE | 0x10 | Set on ACEs created through inheritance (not explicitly placed). Determines ordering in canonical form. |

## 5.6.2 Common flag combinations

| Flags | Meaning |
|---|---|
| CI \| OI | Inherit to everything — containers and non-containers, recursively. |
| CI | Inherit to containers only, recursively. |
| OI | Inherit to non-containers only. Containers receive it as inherit-only. |
| CI \| OI \| IO | Inherit to everything, but do not apply to this object. |
| CI \| OI \| NP | Inherit to immediate children only. |
| CI \| NP | Inherit to immediate child containers only. |
| (none) | No inheritance. Applies only to this object. |

## 5.6.3 CREATOR OWNER and CREATOR GROUP

Two well-known SIDs receive special treatment during inheritance:

- **CREATOR OWNER (`S-1-3-0`)** — when an ACE with this SID is inherited
  by a child object, the SID is replaced with the owner SID of the new
  object (as determined by the owner computation above).

- **CREATOR GROUP (`S-1-3-1`)** — replaced with the primary group SID of
  the creating principal.

Substitution happens at inheritance time. The resulting ACE on the child
contains the resolved SID, not the placeholder.

## 5.6.4 Inheritance algorithm

When a new object is created, its SD is computed from up to three
sources:

1. **Parent SD** — provides inheritable ACEs.
2. **Creator SD** — an explicit SD provided by the caller (if any).
3. **Creator token** — provides the default owner, primary group, and
   default DACL.

A creator SD with SE_SERVER_SECURITY set is rejected; see §5.1.

### 5.6.4.1 Owner

If the creator SD specifies an owner, use it. Otherwise, use the token's
owner SID.

### 5.6.4.2 Group

If the creator SD specifies a group, use it. Otherwise, use the token's
primary group SID.

### 5.6.4.3 DACL

The DACL is computed by merging explicit ACEs from the creator SD with
inheritable ACEs from the parent SD:

- If no creator SD is supplied and the parent has inheritable ACEs: the
  new object's DACL consists entirely of inherited ACEs from the parent.

- If no creator SD is supplied and the parent has no inheritable ACEs:
  the new object's DACL is the token's default DACL. If the token has no
  default DACL, the new object's DACL is null: SE_DACL_PRESENT is clear
  and the DACL offset is zero.

- If a creator SD is supplied but has no DACL (SE_DACL_PRESENT not set):
  the new object's DACL is computed as if no creator SD was supplied
  (inherit from parent, or fall back to the token's default DACL, or
  null DACL if the token has no default DACL).

- If a creator SD is supplied with a DACL (SE_DACL_PRESENT set):
  - Explicit ACEs from the creator SD are preserved.
  - If the creator SD's DACL is not protected (SE_DACL_PROTECTED not
    set) and SE_DACL_AUTO_INHERIT_REQ is set on the creator SD:
    inheritable ACEs from the parent are appended after the explicit
    ACEs. If SE_DACL_AUTO_INHERIT_REQ is not set, only the creator's
    explicit ACEs are used (no parent inheritance).
  - If the creator SD's DACL is protected: parent inheritance is
    blocked. Only the creator's explicit ACEs are used.

In all cases, the resulting DACL is post-processed:

- CREATOR OWNER / CREATOR GROUP SIDs are substituted with the actual
  owner and group. This substitution applies to the ACE's SID field
  only. ApplicationData — conditional expression bytecode — is copied
  verbatim: no SID substitution, no generic mapping, no offset
  adjustment. An implementation MUST NOT scan ApplicationData for
  CREATOR OWNER or CREATOR GROUP SIDs.
- Generic rights in all ACEs (both explicit and inherited) are mapped to
  object-specific rights via the object type's GenericMapping. This
  ensures no unresolved generic bits persist on stored ACEs. Generic
  rights appearing inside ApplicationData are not mapped.
- The INHERITED_ACE flag is set on all ACEs that came from the parent.
- If any ACE was inherited from the parent, SE_DACL_AUTO_INHERITED is
  set on the new SD's control flags; if the DACL came from the token's
  default DACL instead, SE_DACL_DEFAULTED is set. The equivalent applies
  to SE_SACL_AUTO_INHERITED for the SACL.

An ACE of an unrecognised type is carried to the child unchanged apart
from its AceFlags byte (§5.4). Its mask is not mapped and its SID is not
substituted, because neither can be located within an opaque ACE.

### 5.6.4.4 SACL

Computed identically to the DACL, substituting SACL for DACL throughout.
The token has no "default SACL" — if no creator SACL is supplied and the
parent has no inheritable SACL ACEs, the new object has no SACL.

## 5.6.5 Eager evaluation

Inheritance is eager. The new object's SD is fully computed at creation
time. There is no lazy inheritance — the kernel MUST NOT walk up the
directory tree at access time to find inheritable ACEs.

A consequence of eager evaluation: modifying an inheritable ACE on a
parent object does not automatically update existing children. Existing
children retain the SD they were created with. Propagating the change to
descendants is an explicit operation outside the scope of this document.
Children with SE_DACL_PROTECTED or SE_SACL_PROTECTED set MUST be skipped
during any re-propagation.
