Resources, Contexts and Capabilities
Resources
Resources are provided by the execution context. They are linear and should be recycled exactly once.
Capabilities
Dynamic capabilities: run-time objects that allow specific run-time actions. Structured linear collections of values + value-specific actions + limits on actions?. $$ Capability = (object, action, limits)$$ Capability objects usually allow narrowing down to a narrower capability (either consuming or uniqrefing their parent capability?). Or a narrower capability can be split from the parent (e.g. a buffer from a buffer).
Static capabilities:
- rewriting code in a scope (e.g. async) during compilation
- ensuring that some dynamic capability cannot be used in a scope (e.g. no
core.mem
, nocore.alloc
, nocore.panic
, noos
).
It only makes sense for non-native, emulated/JIT execution. Already compiled native code can use them, but should not be trusted not to use other capabilities.
-
proc.memory
: object: the entire process memory; actions: peek, poke, transmute. This is roughly unsafe Rust. This capability is special: having random memory access capability means having the ability to get all other capabilities as well. Can objects be reduced to specific buffers? -
proc.alloc
: object: heaps and their memory; actions: malloc, realloc, free. -
proc.panic
: object: thread, action: exit/abort/atexit; not giving this to a library gives you#[no_panic]
in Rust. -
proc.mmap
: object: process memory segments, actions: mmap/munmap, listing segments of the current process and libraries, managing JIT segments, etc. -
proc.lib
: object: shared libraries, actions: list, search, dlopen/dlsym/... -
proc.thread
: objects: pthreads; actions: spawn, kill, synchronize; -
proc.async
: green threads, async/await? This is an interesting case: importing this capability changes how compiler generates code ("const-capability"?). -
os.io
: objects: stdin/stdout/stderr, actions: read/write/close. -
os.fs
: a list of directories + actions on them; ability to open/read/write files. -
os.proc
: interacting with other processes: getpid, fork, exec, kill, pipes, popen, ptrace; IPC? -
os.time
: a dict of clocks (walltime, monotonic, high-precision, etc) and timers -
os.signal
? -
os.user
: objects: UIDs/GIDs, actions: getuid/setuid/setgid/... -
net.dns
: object: DNS domains or wildcards, actions: resolving DNS records -
net.ip
: object: IP endpoints, actions: gettingip addr/ip link
info? -
net.tcp
: object: a TCP endpoint (IP endpoint + TCP port), actions: connecting, send/recv -
net.udp
: same asnet.tcp
-
gpu.???
: access to GPU contexts, draw calls, textures, shaders, etc. -
cap.manage
: managing/introspecting capabilities themselves?
Static capabilities.
- async: allows rewriting code of a scope into state machines at compile time.
- no panic: statically guarantees that no panics can come out of this scope.
- no alloc: statically guarantees that no allocations can happen in this scope.
- safe memory: statically verified absense of direct
core.mem
usage.
References:
Open questions:
Safe code built on unsafe code. In other words, interplay between capabilities and modules/packages. E.g. std.Rc
must use proc.memory
capability.
- but it's in
std
, can receive this authority viastd.init()
or something. Then it decides which modules getproc.memory
? - Modules get a capability statically: capability might be present in a loaded package instance, but statically verified to not be used in a specific module.
- Getting a capability via memory introspection: possible using
proc.memory
.
Capabilities might be indirect:
- writing to a file on NFS causes network requests;
- ability to write
/proc/self/mem
means havingcore.mem
(no language is truly memory safe on Linux!). - Opaque data can smuggle dynamic capabilities through a module that prohibits this capability (e.g. passing a reference to an allocator through a no-alloc module)?
- Any piece of code with access to capabilities can implement a Turing-complete interpreter that makes static analysis of effects undecidable in general and then provide its capabilities to third-party code indirectly. Is static analysis of capabilities feasible at all? How limited a statically-verifiable version would be?