Pure-Capability Systems

Pure-capability systems represent language-visible pointers as capabilities throughout compiled software, applying CHERI checks broadly across the system.

Selective capabilities can protect selected buffers and interfaces, but ordinary pointers elsewhere may still authorise broad access. A pure-capability application binary interface, or ABI, takes the wider step: language-visible pointers are represented as capabilities throughout the relevant compiled software.

This is the main route for applying CHERI memory protection across existing C and C++ code without rewriting every component in a different language.

What changes in the ABI

An ABI defines how compiled components agree on calls, data layout, registers, binaries, and system interfaces. In a pure-capability ABI:

Every linked component at an interface must follow compatible rules.

Where capabilities come from

The operating system and program loader establish initial capabilities for code, globals, stack, and mapped memory. The runtime and allocator derive capabilities for objects. The compiler then uses those capabilities for ordinary source-level pointer operations.

This means a source declaration such as:

char *buffer = malloc(128);

can produce a capability bounded to the allocation. Loads and stores through buffer are checked by the processor without requiring the source programmer to call a CHERI instruction for each access.

Benefits

Pure-capability systems provide:

Large bodies of Unix software have been ported through CheriBSD, showing that this model can support complete operating-system and application stacks.

Common porting changes

Well-structured source often compiles with little change. Problems usually appear where code:

These are often latent portability or security problems even before CHERI. The pure-capability build makes them visible.

Pointer size and performance

Capabilities carry more information than ordinary addresses. Depending on the architecture, this can increase pointer storage, memory traffic, structure size, or register pressure. Capability compression reduces the representation cost, and compiler, allocator, and microarchitecture choices influence the result.

There is no universal performance overhead. Pointer-heavy data structures, system calls, cache behaviour, and compartment transitions affect workloads differently. Measure the intended application on the intended implementation.

Pure capability is not the same as compartmentalised

A pure-capability process can still begin with capabilities for most of its address space. Its pointers are protected by bounds and permissions, but every library may remain part of one large trust domain.

Compartmentalisation deliberately divides the capabilities held by different components. It is an additional architecture and software design step.

Pure capability is not a complete security guarantee

How to verify the mode

The hardware name alone does not establish pure-capability operation. Check:

CheriBSD, Morello software, CHERI-RISC-V software development kits (SDKs), and CHERIoT use different target names and ABIs. Use their current documentation.

Pure-capability software offers broad pointer protection. Compartmentalisation explains how to reduce the set of objects and services that each component can reach.

Where next

A short account of early capability-based computer systems and the ideas that influenced later work.

Early Capability Systems →