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 |
|---|---|---|---|
|
|
8 |
Pointer to the KernelObject header of the named object. |
|
|
8 |
Identifies the sender in IPC. Set by |
|
|
4 |
Bitmap of permitted operations. See Rights. |
|
|
1 |
Object type discriminant (must match the object’s |
|
|
1 |
Number of derivation steps from the original. Bounded by |
|
|
2 |
Reserved for future use. |
|
|
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 |
|---|---|---|
|
0 |
Read access (memory mappings, I/O port input) |
|
1 |
Write access (memory mappings, I/O port output) |
|
2 |
Execute access (code page mappings) |
|
3 |
Derive new capabilities via |
|
4 |
Revoke derived capabilities |
|
5 |
Send to an endpoint |
|
6 |
Receive from an endpoint |
|
7 |
Atomic send-then-receive (client RPC) |
|
8 |
One-shot reply capability |
|
9 |
Configure thread or scheduling parameters |
|
10 |
Suspend a thread |
|
11 |
Resume a thread |
|
12 |
Map pages into a VSpace |
|
13 |
Unmap pages from a VSpace |
|
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
copyoperation. A capability withoutGRANTcannot 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:
- Layer 1 — Kernel objects
-
The actual resources (endpoints, threads, memory, etc.). Each carries a
KernelObjectheader with type and reference count. - Layer 2 — Global slot array
-
A boot-time allocated array of
CapSlotStorageentries, each containing a 32-byteCapabilitypayload and aCapSlotMetastructure 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
CapRefindices (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_rightsis 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_rightsanddepth = source.depth + 1. -
The new slot is inserted as a CDT child of the source.
-
The object’s reference count is incremented.
-
A
CapRefis 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
-
EndpointandNotificationonly. - Preconditions
-
-
Source capability has
GRANT. -
new_rightsdoes not includeGRANT. -
Source
depth < MAX_DERIVATION_DEPTH. -
Destination CNode slot is empty.
-
- Effects
-
Same as
copy, but additionally writesbadgeinto 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
-
Endpointonly. - 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
-
-
Remove from CDT (unlink parent/sibling pointers).
-
Remove from untyped-child list (if the slot has a
ut_parent). -
Decrement the object’s reference count; run
destroy_object()if it reaches zero. -
Nullify the capability payload.
-
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_capabilityruns 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
CapRefis written to the destination CNode slot. -
The caller thread’s
reply_tcbfield 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
GRANTcannot be used to derive further capabilities, preventing unauthorized delegation. - Revocability
-
Any capability holder with
REVOKEright can destroy all capabilities derived from its own. - Memory safety
-
Capabilities are kernel-managed and unforgeable. Userspace never sees raw capability data.
Related Pages
-
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