Capabilities

A capability is an unforgeable token that names a kernel object and carries the rights to perform operations on it. Capabilities are the sole mechanism for accessing kernel resources — no ambient authority exists. Only the kernel can create, modify, or transfer capabilities.

Capability Structure

Each capability is exactly 32 bytes, stored by value in the global slot array:

#[repr(C)]
pub struct Capability {       // 32 bytes total
    pub object: *mut KernelObject,  // 8 bytes — pointer to kernel object
    pub badge: u64,                 // 8 bytes — IPC identification tag
    pub rights: CapRights,          // 4 bytes — access rights bitmap
    pub obj_type: ObjectType,       // 1 byte  — object type discriminant
    pub depth: u8,                  // 1 byte  — derivation depth
    pub _reserved: u16,             // 2 bytes
    pub _pad: u64,                  // 8 bytes
}
Offset Field Size Purpose

0x00

object

8

Pointer to the KernelObject header of the named object.

0x08

badge

8

Identifies the sender in IPC. Set by mint; zero for unbadged capabilities.

0x10

rights

4

Bitmap of permitted operations. See Rights.

0x14

obj_type

1

Object type discriminant (must match the object’s KernelObject.obj_type).

0x15

depth

1

Number of derivation steps from the original. Bounded by MAX_DERIVATION_DEPTH = 64.

0x16

_reserved

2

Reserved for future use.

0x18

_pad

8

Padding to 32-byte alignment.

The fixed 32-byte size enables storage in a dense array and copy-by-value during derivation.

A null capability has object = null, obj_type = Null, and all other fields zero.

Rights

The CapRights type is a 32-bit bitmap. Each bit gates a specific class of operation:

Right Bit Meaning

READ

0

Read access (memory mappings, I/O port input)

WRITE

1

Write access (memory mappings, I/O port output)

EXECUTE

2

Execute access (code page mappings)

GRANT

3

Derive new capabilities via copy. Required for delegation.

REVOKE

4

Revoke derived capabilities

SEND

5

Send to an endpoint

RECV

6

Receive from an endpoint

CALL

7

Atomic send-then-receive (client RPC)

REPLY

8

One-shot reply capability

CONFIGURE

9

Configure thread or scheduling parameters

SUSPEND

10

Suspend a thread

RESUME

11

Resume a thread

MAP

12

Map pages into a VSpace

UNMAP

13

Unmap pages from a VSpace

RETYPE

14

Retype untyped memory into typed objects

CapRights::ALL sets all 32 bits. Newly retyped objects receive CapRights::ALL. Rights can only be reduced during derivation, never increased.

Two rights have cross-cutting significance:

GRANT

Gates the copy operation. A capability without GRANT cannot be used to derive new capabilities. This is the mechanism for confinement — a process holding a send-only endpoint capability cannot delegate it further.

REPLY

Set on one-shot reply capabilities created by save_caller. A reply capability names a TCB and permits exactly one reply.

Three-Layer Architecture

Capability state is split across three layers:

Diagram
Layer 1 — Kernel objects

The actual resources (endpoints, threads, memory, etc.). Each carries a KernelObject header with type and reference count.

Layer 2 — Global slot array

A boot-time allocated array of CapSlotStorage entries, each containing a 32-byte Capability payload and a CapSlotMeta structure with CDT and untyped tracking links. This is the authoritative store of all live capabilities. See Global Slot Array.

Layer 3 — CNodes

Kernel objects that store CapRef indices (not embedded capabilities) into the global slot array. CNodes form a thread’s CSpace — the namespace through which it addresses capabilities. See CSpace.

CNode entries are references, not storage. Deleting a CNode entry does not delete the capability — it removes one reference to a global slot. Multiple CNodes can hold CapRef values pointing to the same global slot.

Derivation Tree

The Capability Derivation Tree (CDT) tracks the parent-child relationships between capabilities. It is stored as linked-list pointers in the CapSlotMeta of each global slot:

pub struct CapSlotMeta {
    pub cdt_parent: CapSlot,       // parent slot (INVALID_SLOT if root)
    pub cdt_first_child: CapSlot,  // head of child list
    pub cdt_next: CapSlot,         // next sibling
    pub cdt_prev: CapSlot,         // previous sibling
    // ... untyped tracking fields ...
    pub state: SlotState,
}

Key properties:

  • Each slot has at most one CDT parent.

  • Each slot can have zero or more children, linked as a doubly-linked sibling list.

  • Child insertion is O(1): new children are pushed at the head of the parent’s child list.

  • Derivation is tracked at the slot level, not the object level.

The CDT enables two operations that require knowledge of authority provenance:

  • Revocation: recursively destroy all capabilities derived from a given slot.

  • Untype: reclaim an object back to its parent untyped memory, which requires that no derived capabilities exist.

Capability Operations

Copy

copy creates a new capability that references the same object with equal or reduced rights.

Preconditions
  • Source capability has GRANT.

  • new_rights is a subset of the source’s rights.

  • Source depth < MAX_DERIVATION_DEPTH (64).

  • Destination CNode slot is empty.

Effects
  • A fresh global slot is allocated.

  • The capability payload is copied by value with rights = new_rights and depth = source.depth + 1.

  • The new slot is inserted as a CDT child of the source.

  • The object’s reference count is incremented.

  • A CapRef is written to the destination CNode slot.

copy produces a new, independent slot. It is not aliasing.

Mint

mint creates a badged capability. It is stricter than copy.

Allowed object types

Endpoint and Notification only.

Preconditions
  • Source capability has GRANT.

  • new_rights does not include GRANT.

  • Source depth < MAX_DERIVATION_DEPTH.

  • Destination CNode slot is empty.

Effects

Same as copy, but additionally writes badge into the destination capability.

The GRANT exclusion is intentional: a badged capability is a delegation dead-end. The holder can use it (e.g., send to the endpoint) but cannot derive further capabilities from it.

Move

move transfers a CapRef from one CNode slot to another.

Effects
  • The source CNode entry is set to null.

  • The destination CNode entry receives the CapRef.

  • No new global slot is allocated.

  • No reference count change.

  • No CDT change.

Move is purely a CSpace-level operation.

Mutate

mutate moves a capability and overwrites its badge.

Allowed object types

Endpoint only.

Effects

Performs a move, then writes a new badge value into the capability payload at the destination slot.

Delete

delete removes a single capability slot.

Preconditions
  • The slot has no CDT children.

Effects
  1. Remove from CDT (unlink parent/sibling pointers).

  2. Remove from untyped-child list (if the slot has a ut_parent).

  3. Decrement the object’s reference count; run destroy_object() if it reaches zero.

  4. Nullify the capability payload.

  5. Free the global slot.

Delete is idempotent: calling it on an already-free slot is a no-op.

Revoke

revoke destroys an entire authority subtree.

Algorithm

Depth-first recursive traversal of CDT descendants. For each descendant (leaf-first), delete_capability runs the full deletion lifecycle. After all descendants are removed, the target slot itself is deleted.

Properties
  • No heap allocation. Recursion depth is bounded by MAX_DERIVATION_DEPTH (64).

  • Revoke is the only operation that tears down a subtree of authority.

  • After revoke, the target object may still exist if other non-descendant capabilities reference it.

Save Caller (Reply Capability)

save_caller synthesizes a one-shot reply capability.

Effects
  • A fresh global slot is allocated.

  • A capability is created with obj_type = Tcb, rights = REPLY, referencing the caller’s TCB.

  • The TCB’s reference count is incremented.

  • The CapRef is written to the destination CNode slot.

  • The caller thread’s reply_tcb field is cleared.

Reply authority is explicit slot state, not ambient thread state.

Security Properties

No ambient authority

A thread can only access objects for which it holds a capability in its CSpace.

Monotonic attenuation

Rights can only be reduced during derivation (copy, mint), never increased.

Confinement

A capability without GRANT cannot be used to derive further capabilities, preventing unauthorized delegation.

Revocability

Any capability holder with REVOKE right can destroy all capabilities derived from its own.

Memory safety

Capabilities are kernel-managed and unforgeable. Userspace never sees raw capability data.

  • Object Model — kernel object types and lifecycle

  • CSpace — capability storage, CNode layout, and address resolution

  • Capability Invocations — CNode invoke labels for copy/mint/move/delete/revoke