Modern operating systems enforce security boundaries between processes, files, devices, and users. However, the way these boundaries are implemented varies significantly across system designs.

Most mainstream operating systems rely on identity-based access control and global namespaces. Capability-based operating systems take a fundamentally different approach: they represent authority explicitly and make it a first-class concept.

This post introduces capability-based systems, explains how they differ from traditional designs, and outlines why they are central to the design of EriX.


The Problem: Ambient Authority

In traditional systems, processes often have access to resources through ambient authority.

Ambient authority means that a program can access a resource simply because it exists in a shared namespace and the system determines that the program has permission to use it.

For example:

  • A process can open /etc/passwd if it has sufficient permissions.
  • A program can connect to a network socket if it is allowed by the OS.
  • A service can access files based on user identity or group membership.

In all of these cases, the authority to access a resource is implicit.

The process does not hold a direct, explicit reference to the resource. Instead, it relies on:

  • global names (file paths, ports, device identifiers)
  • access control checks (user IDs, permissions, ACLs)

This model creates several problems:

1. Confused Deputy Problem

A program may accidentally misuse its authority on behalf of another program.

For example, a privileged service might read a file requested by an untrusted client, even if the client itself should not have access.

2. Overly Broad Authority

Programs often run with more permissions than they actually need. This increases the impact of bugs or compromises.

3. Difficult Reasoning

It is hard to determine what a process is allowed to do without analyzing global state, user identities, and access control policies.


The Core Idea: Capabilities

A capability is an unforgeable token that grants access to a specific object with specific rights.

Instead of asking:

“Does this process have permission to access this resource?”

a capability-based system asks:

“Does this process possess a capability that authorizes this operation?”

If the answer is no, the operation cannot proceed.


Properties of Capabilities

Capabilities have several defining properties:

1. Unforgeability

A process cannot create a valid capability out of thin air.

Capabilities are created and managed by the kernel, ensuring that they cannot be faked or guessed.


2. Explicit Authority

All authority is represented explicitly through capabilities.

If a process can perform an operation, it must possess a capability that allows it. There is no implicit access via global namespaces.


3. Fine-Grained Rights

Capabilities can encode specific permissions, such as:

  • read-only access
  • write access
  • execute permissions
  • limited subsets of operations

This allows precise control over what each process can do.


4. Transferability

Capabilities can be transferred between processes, typically via inter-process communication (IPC).

This enables controlled delegation of authority.


Objects and Capabilities

In a capability-based system, everything is modeled as an object:

  • memory regions
  • files
  • devices
  • IPC endpoints
  • processes

A capability is a reference to an object, combined with a set of rights.

A process interacts with the system by invoking operations on objects through its capabilities.

There is no need for global names like file paths or device identifiers inside the kernel. All access is mediated through capabilities.


How Capability Systems Work

At a high level, a capability-based system operates as follows:

  1. The kernel creates objects and capabilities.
  2. Each process has a capability space (often called a CSpace), which stores its capabilities.
  3. A process can only operate on objects for which it holds capabilities.
  4. Capabilities can be transferred between processes via IPC.
  5. The kernel enforces all capability checks.

This results in a system where authority is:

  • explicit
  • localized
  • transferable
  • easy to reason about

Example: Opening a File

Traditional Model

In a traditional system:

  1. A process calls open("/etc/config")
  2. The kernel checks permissions:
    • user ID
    • group membership
    • file mode bits
  3. If allowed, a file descriptor is returned

The authority comes from global state and identity.


Capability-Based Model

In a capability system:

  1. A process must already possess a file capability
  2. It uses that capability to perform read/write operations

If the process does not have the capability, it cannot access the file—no matter what name it uses.

There is no global lookup step inside the kernel.


Delegation and Least Privilege

One of the most powerful aspects of capability systems is delegation.

A process can give another process a subset of its authority by transferring a capability.

For example:

  • A file server gives a client read-only access to a file
  • A memory manager grants access to a specific memory region
  • A process grants access to an IPC endpoint

This enables the principle of least privilege:

Each component receives only the authority it actually needs.


Eliminating Ambient Authority

Capability systems eliminate ambient authority entirely.

There are:

  • no global namespaces inside the kernel
  • no implicit access based on identity
  • no hidden privileges

All authority must be explicitly passed.

This makes it much easier to analyze:

  • what a process can do
  • how authority flows through the system
  • where potential security issues may arise

Revocation (A Hard Problem)

One challenge in capability systems is revocation.

Once a capability is given to a process, how can it be taken away?

Different systems implement revocation in different ways:

  • indirection layers
  • reference tracking
  • capability trees
  • versioning mechanisms

Revocation is an important area of research and will be explored in later stages of EriX.


Capability Systems in Practice

Capability-based ideas are not new. Several systems have implemented them:

  • KeyKOS / EROS
  • seL4 (a formally verified microkernel)
  • CHERI (hardware-assisted capabilities)
  • Capsicum (capability extensions for FreeBSD)

These systems demonstrate that capability-based designs are both practical and powerful.


How EriX Uses Capabilities

EriX is designed from the ground up as a capability-based system.

In EriX:

  • all authority is represented through capabilities
  • capabilities are strongly typed
  • capabilities are immutable once created
  • capabilities are transferred via IPC
  • the kernel enforces non-forgeability and safety invariants

There are no global namespaces inside the kernel. All resource access is mediated through capabilities.

This aligns with the broader goal of making authority:

  • explicit
  • minimal
  • easy to reason about

Why This Matters

Capability-based systems provide a foundation for building:

  • more secure systems
  • more modular architectures
  • systems that are easier to analyze and verify

By removing implicit authority and making all access explicit, they eliminate entire classes of vulnerabilities that are common in traditional systems.


Looking Ahead

Capabilities are a foundational concept in EriX. In future posts, we will explore how they are implemented in practice, including:

  • capability spaces (CSpace)
  • inter-process communication (IPC)
  • memory management using untyped capabilities
  • delegation and authority graphs

Understanding capabilities is the first step toward understanding the rest of the system.