Capability System

Relevant source files

Purpose and Scope

The Capability System forms the foundation of access control in the cap_access library. This document covers the Cap bitflags structure, the three fundamental capability types (READ, WRITE, EXECUTE), and the mechanisms for combining and checking capabilities. For information about how capabilities are used with protected objects, see Object Protection with WithCap. For details on access control methods that utilize these capabilities, see Access Control Methods.

Cap Bitflags Structure

The capability system is implemented using the bitflags crate to provide efficient bit-level operations for permission management. The Cap structure represents unforgeable access tokens that can be combined using bitwise operations.

flowchart TD
subgraph subGraph2["Bitwise Operations"]
    UNION["Union (|)"]
    INTERSECTION["Intersection (&)"]
    CONTAINS["contains()"]
end
subgraph subGraph1["Bitflags Traits"]
    DEFAULT["Default"]
    DEBUG["Debug"]
    CLONE["Clone"]
    COPY["Copy"]
end
subgraph subGraph0["Cap Structure [lines 4-15]"]
    CAP["Cap: u32"]
    READ["READ = 1 << 0"]
    WRITE["WRITE = 1 << 1"]
    EXECUTE["EXECUTE = 1 << 2"]
end

CAP --> CLONE
CAP --> COPY
CAP --> DEBUG
CAP --> DEFAULT
CAP --> EXECUTE
CAP --> READ
CAP --> WRITE
EXECUTE --> UNION
INTERSECTION --> CONTAINS
READ --> UNION
UNION --> CONTAINS
WRITE --> UNION

Cap Bitflags Architecture

The Cap struct is defined as a bitflags structure that wraps a u32 value, providing type-safe capability manipulation with automatic trait derivations for common operations.

Sources: src/lib.rs(L4 - L15) 

Basic Capability Types

The capability system defines three fundamental access rights that correspond to common operating system permissions:

CapabilityBit PositionValuePurpose
READ01 << 0(1)Grants readable access to protected data
WRITE11 << 1(2)Grants writable access to protected data
EXECUTE21 << 2(4)Grants executable access to protected data
flowchart TD
subgraph subGraph1["Capability Constants"]
    READ_CONST["Cap::READ = 0x01"]
    WRITE_CONST["Cap::WRITE = 0x02"]
    EXECUTE_CONST["Cap::EXECUTE = 0x04"]
end
subgraph subGraph0["Bit Layout [u32]"]
    BIT2["Bit 2: EXECUTE"]
    BIT1["Bit 1: WRITE"]
    BIT0["Bit 0: READ"]
    UNUSED["Bits 3-31: Reserved"]
end

BIT0 --> READ_CONST
BIT1 --> WRITE_CONST
BIT2 --> EXECUTE_CONST

Capability Bit Layout

Each capability type occupies a specific bit position, allowing for efficient combination and checking operations using bitwise arithmetic.

Sources: src/lib.rs(L8 - L14) 

Capability Combinations

Capabilities can be combined using bitwise OR operations to create composite permissions. The bitflags implementation provides natural syntax for capability composition:

flowchart TD
subgraph subGraph2["Use Cases"]
    READONLY["Read-only files"]
    READWRITE["Mutable data"]
    EXECUTABLE["Program files"]
    FULLACCESS["Administrative access"]
end
subgraph subGraph1["Common Combinations"]
    RW["Cap::READ | Cap::WRITE"]
    RX["Cap::READ | Cap::EXECUTE"]
    WX["Cap::WRITE | Cap::EXECUTE"]
    RWX["Cap::READ | Cap::WRITE | Cap::EXECUTE"]
end
subgraph subGraph0["Single Capabilities"]
    R["Cap::READ"]
    W["Cap::WRITE"]
    X["Cap::EXECUTE"]
end

R --> READONLY
R --> RW
R --> RWX
R --> RX
RW --> READWRITE
RWX --> FULLACCESS
RX --> EXECUTABLE
W --> RW
W --> RWX
W --> WX
X --> RWX
X --> RX
X --> WX

Capability Combination Patterns

The bitflags design enables natural combination of capabilities to express complex permission requirements.

Sources: src/lib.rs(L4 - L15) 

Capability Checking Logic

The capability system provides the contains method for checking whether a set of capabilities includes required permissions. This forms the foundation for all access control decisions in the system.

flowchart TD
subgraph subGraph0["contains() Logic"]
    BITWISE["(self.bits & other.bits) == other.bits"]
    SUBSET["Check if 'other' is subset of 'self'"]
end
subgraph subGraph1["Example Scenarios"]
    SCENARIO1["Object has READ|WRITERequest: READ → true"]
    SCENARIO2["Object has READRequest: WRITE → false"]
    SCENARIO3["Object has READ|WRITERequest: READ|WRITE → true"]
end
START["can_access(cap: Cap)"]
CHECK["self.cap.contains(cap)"]
TRUE["Return true"]
FALSE["Return false"]

BITWISE --> SUBSET
CHECK --> BITWISE
START --> CHECK
SUBSET --> FALSE
SUBSET --> TRUE

Capability Checking Flow

The can_access method uses bitwise operations to determine if the requested capabilities are a subset of the available capabilities.

Sources: src/lib.rs(L46 - L48) 

Implementation Details

The Cap structure leverages several key design patterns for efficient and safe capability management:

Bitflags Integration

The implementation uses the bitflags! macro to generate a complete capability management API, including:

  • Automatic implementation of bitwise operations (|, &, ^, !)
  • Type-safe flag manipulation methods
  • Built-in contains() method for subset checking
  • Standard trait implementations (Debug, Clone, Copy, Default)

Memory Efficiency

The Cap structure occupies only 4 bytes (u32) regardless of capability combinations, making it suitable for embedded environments where memory usage is critical.

Constant Evaluation

The can_access method is marked as const fn, enabling compile-time capability checking when capability values are known at compile time.

Sources: src/lib.rs(L4 - L15)  src/lib.rs(L46 - L48)