cap.nx
buildroot/runtime/cap.nx
about
cap.nx -- capability-based security primitives.
EFFICIENCY_ROADMAP ยง5.4. Today every .nx file can call any
syscall (sys_execve, sys_openat, etc.) because the function
symbols are linker-resolved with no access control. That's
fine for a single-author project; it's a disaster once we
import third-party code.
This module ships capability tokens that can be REQUIRED at
function-signature level. A function that wants to open a
file takes a `*CapFS` argument; if the caller didn't get that
capability from the root process, they can't forge one (we
don't expose a fake constructor).
Three delivery phases:
A (this file): capability types + a root-only constructor.
Library code adopting `fs_open(cap: *CapFS, path: *u8)`
becomes sandbox-aware immediately; old `fs_open(path)`
callers keep working until migration is complete.
B (parse.nx change, pending): `@requires(CapFS)` function
attribute lifts this into the type system. Compiler
refuses to compile a function that calls fs_open without
a CapFS in scope.
C (import.nx change, pending): every import statement
declares what caps it needs. main.c picks them up +
ensures the top-level main has the superset granted.
Invariants:
CAP1 Capabilities can NOT be forged -- only created through
cap_root_grant which the root/init code holds.
CAP2 A capability can be narrowed (cap_narrow returns a
strictly weaker capability).
CAP3 Capabilities can be revoked; revoked caps reject all
operations + can't be re-enabled.
dependencies 1 imports · 0 importers
imports: syscalls.nx
imported by: nobody (leaf or entry point)
call flow from main pre-order; caps 40 nodes / depth 6 declared; ↻ = already shown
structs
| 69 | struct Cap { |
consts
| 43 | const CAP_FS: i64 = 1 |
| 44 | const CAP_NET: i64 = 2 |
| 45 | const CAP_PROC: i64 = 3 // fork/exec |
| 46 | const CAP_CLOCK: i64 = 4 // reading wall-clock time |
| 47 | const CAP_RANDOM: i64 = 5 |
| 48 | const CAP_ENV: i64 = 6 // environment variables |
| 49 | const CAP_USER: i64 = 7 // setuid/setgid-class ops |
| 53 | const CAP_FS_READ: i64 = 0x01 |
| 54 | const CAP_FS_WRITE: i64 = 0x02 |
| 55 | const CAP_FS_CREATE: i64 = 0x04 |
| 56 | const CAP_FS_DELETE: i64 = 0x08 |
| 57 | const CAP_FS_ALL: i64 = 0x0F |
| 59 | const CAP_NET_BIND: i64 = 0x01 |
| 60 | const CAP_NET_CONNECT: i64 = 0x02 |
| 61 | const CAP_NET_LISTEN: i64 = 0x04 |
| 62 | const CAP_NET_ALL: i64 = 0x07 |
| 64 | const CAP_ERR_REVOKED: i64 = -1 |
| 65 | const CAP_ERR_INSUFFICIENT: i64 = -2 |
functions
| 78 | func cap_root_grant(domain: i64, actions: i64) -> *Cap {
called by 1: main |
| 90 | func cap_narrow(parent: *Cap, actions: i64) -> *Cap {
called by 1: main |
| 101 | func cap_revoke(c: *Cap) -> i64 {
called by 1: main |
| 109 | func cap_check(c: *Cap, domain: i64, actions: i64) -> i64 {
called by 1: main |
| 118 | func main() -> i64 { |