Execution Lifecycle
Overview
Section titled “Overview”Phase 1: Setup
Section titled “Phase 1: Setup”Isolate::new(config) allocates a UID from the atomic bitset pool (60000-60999), creates a cgroup, and captures a baseline snapshot of the workspace.
Phase 2: Execution
Section titled “Phase 2: Execution”execute_code_string() is language-aware:
- Python: Writes source to a temp file, runs
python3 <file> - C++: Compiles with
g++ -O2 -std=c++17, runs the binary - Java: Compiles with
javac, runs withjava Main
Phase 3: Supervision
Section titled “Phase 3: Supervision”The Supervisor clone()s into new namespaces. The Proxy fork()s the actual payload:
Supervisor (host) └── Proxy (namespaced) └── Payload (namespaced + chrooted + cgroup + seccomp)If CPU or wall time expires, the Supervisor kills with SIGKILL immediately. Untrusted code doesn’t get a graceful shutdown.
Phase 4: Evidence collection
Section titled “Phase 4: Evidence collection”After the payload exits, the Supervisor collects wait status, cgroup evidence, timing, and process lifecycle data. This evidence bundle is immutable once collected.
Phase 5: Cleanup
Section titled “Phase 5: Cleanup”- Kill remaining processes in the cgroup
- Verify the baseline (workspace state matches snapshot)
- Remove the cgroup hierarchy
- Wipe the workspace (fd-safe, no symlink following)
- Release the UID back to the pool