These docs are under active development and cover the v0.20 Kobicha security model.
On this page
§5.1

SD Structure

A Security Descriptor (SD) defines the complete security policy for a protected object. Every protected object in Peios -- every file, registry key, IPC endpoint, service, token, and process -- MUST have a Security Descriptor.

An SD has four components and a set of control flags:

  • Owner SID — the principal that owns the object. The owner has implicit rights (READ_CONTROL and WRITE_DAC) unless suppressed by an OWNER RIGHTS ACE.

  • Group SID — a primary group associated with the object. Stored and returned on query, used during CREATOR GROUP substitution during inheritance, but no access control decision depends on it directly.

  • DACL (Discretionary Access Control List) — an ordered list of ACEs that define who is allowed or denied access. The object's owner controls the DACL (via WRITE_DAC).

  • SACL (System Access Control List) — an ordered list of ACEs that define system-level policy. Despite the name, the SACL carries several distinct ACE types:

    • Audit ACEs — which access attempts to log.
    • Mandatory label ACE — the object's integrity level for MIC.
    • Resource attribute ACEs — name-value attributes for conditional ACE evaluation.
    • Scoped policy ID ACEs — references to central access policies.
    • Process trust label ACE — the object's PIP trust level.

    Modifying the SACL requires ACCESS_SYSTEM_SECURITY, which in turn requires SeSecurityPrivilege.

§5.1.1 Binary format

SDs use the self-relative binary format defined in MS-DTYP section 2.4.6. The format is a 20-byte header followed by the owner SID, group SID, SACL, and DACL at offsets specified in the header.

Offset Size Field
0 1 Revision (MUST be 1)
1 1 Reserved. Preserved for format compatibility but not interpreted by KACS. When SE_RM_CONTROL_VALID is set in the control flags, this byte carries resource manager control bits defined by the originating system.
2 2 Control flags (little-endian)
4 4 Offset to owner SID (little-endian, 0 if absent)
8 4 Offset to group SID (little-endian, 0 if absent)
12 4 Offset to SACL (little-endian, 0 if absent)
16 4 Offset to DACL (little-endian, 0 if absent)

The self-relative format packs everything into a contiguous byte buffer with no pointers. This makes it suitable for storage (xattrs, database fields) and wire transmission (IPC, SMB).

KACS MUST use the self-relative format exclusively.

§5.1.2 Control flags

The SD's 16-bit Control field records metadata about the descriptor:

Flag Bit Description
SE_OWNER_DEFAULTED (OD) 0 The owner was established by default means.
SE_GROUP_DEFAULTED (GD) 1 The group was established by default means.
SE_DACL_PRESENT (DP) 2 A DACL is present. If clear, AccessCheck treats the DACL as null.
SE_DACL_DEFAULTED (DD) 3 The DACL was established by default means.
SE_SACL_PRESENT (SP) 4 A SACL is present.
SE_SACL_DEFAULTED (SD) 5 The SACL was established by default means.
SE_DACL_TRUSTED (DT) 6 The DACL was provided by a trusted source.
SE_SERVER_SECURITY (SS) 7 Create a server ACL based on the input ACL.
SE_DACL_AUTO_INHERITED (DI) 10 The DACL was created through automatic inheritance.
SE_SACL_AUTO_INHERITED (SI) 11 The SACL was created through automatic inheritance.
SE_DACL_PROTECTED (PD) 12 The DACL is protected from inheritance. Inheritable ACEs from parent objects MUST NOT be merged.
SE_SACL_PROTECTED (PS) 13 The SACL is protected from inheritance.
SE_RM_CONTROL_VALID (RM) 14 The Sbz1 byte is interpreted as resource manager control bits.
SE_SELF_RELATIVE (SR) 15 The SD is in self-relative format. MUST always be set for stored SDs.

The PROTECTED flags are operationally significant. Setting SE_DACL_PROTECTED prevents inheritance from parent objects -- the object keeps its current ACEs and stops accepting new inheritable ACEs from above.

§5.1.3 Null DACL vs empty DACL

The SE_DACL_PRESENT flag distinguishes two states with very different security consequences:

  • Null DACL (SE_DACL_PRESENT not set) — no discretionary access control. AccessCheck grants all requested access to every caller. This SHOULD almost never be used.

  • Empty DACL (SE_DACL_PRESENT set, zero ACEs) — AccessCheck grants no access to any caller (except the owner's implicit rights). An explicit statement that no principal has discretionary access.

Objects SHOULD always have a DACL. The SD creation algorithm ensures every new object receives one.