Capability drop
The process applies no_new_privs, disables dumpability and core dumps, and sets a file-descriptor ceiling before guest execution.
Isolation at the process, resource, and control boundaries
FlashVMM does not rely on a guest to behave well. CPU, memory, disk capacity, disk I/O, and network traffic are controlled independently for each VM on x86_64 and aarch64. The VMM drops its capabilities and installs per-thread seccomp allowlists before guest code runs, while access to the control socket remains governed by standard Linux file permissions.
| Resource | Mechanism |
|---|---|
| CPU | A signal-based pacer enforces execution limits. |
| Memory | The KVM memory map establishes a hard ceiling; any virtio-mem region is declared inside it, at creation, and enforced with its own ceiling. |
| Disk capacity | A reserve-and-settle quota accounts for storage. |
| Disk I/O | Separate token buckets limit throughput and operations. |
| Network | Three token buckets govern traffic on each NIC. |
A limiter that waits for a vCPU thread to leave KVM_RUN cannot control a guest that minimizes voluntary exits. FlashVMM uses a pacer thread to signal each vCPU every 5ms with tgkill. Because the handler omits SA_RESTART, KVM_RUN returns EINTR and the thread's budget can be checked against CLOCK_THREAD_CPUTIME_ID.
The mechanism does not require cgroups or cooperation from the guest kernel. If the signal handler cannot be installed, the VM is not allowed to run. A configurable boot-grace window, eight seconds by default, defers enforcement during kernel initialization and device probing. Restored VMs receive no grace period.
Memory is fixed by the KVM guest-memory mapping when the VM is created. It is a ceiling, not a rate limit: PATCH /memory returns 422 memory_immutable. The balloon device can return memory to the host or reclaim it while the VM is running, but it cannot exceed the original allocation. A VM created with a virtio-mem region gets a second lever inside that same declared boundary: the host sets a live target, and a request beyond the region's own size is refused outright with 422 mem_exceeds_region rather than silently capped. A VM created without one pays nothing for it — no MMIO window, no attack surface, no boot-time cost.
Disk usage is charged by allocated blocks, with a separate per-inode cost, rather than by the nominal size of a sparse file. Each write reserves capacity before it is admitted and settles against its final charge afterward, keeping concurrent writes within the same quota.
Disk throughput and IOPS are governed by separate token buckets in the io_uring completion path used for FlashVM storage. Limits must be set explicitly at creation; 0 is rejected rather than interpreted as unlimited capacity.
Each NIC has independent limits for egress bandwidth, egress packet rate, and ingress bandwidth. Keeping packet rate separate from throughput prevents a stream of small packets from bypassing a bandwidth-only limit.
Before the first guest instruction runs, the VMM drops its capabilities and applies a dedicated seccomp allowlist to each thread. Access to the VM's control socket is then governed by operating-system file permissions rather than a separate application credential.
sequenceDiagram participant CLI as flash CLI participant Proc as FlashVMM process CLI->>Proc: spawn + exec Proc->>Proc: drop all capabilities Proc->>Proc: no_new_privs, non-dumpable,
no core dump, fd ceiling Proc->>Proc: per-thread seccomp allowlist
(API thread, main thread, each vCPU) Note over Proc: guest code only
executes after this line
The process applies no_new_privs, disables dumpability and core dumps, and sets a file-descriptor ceiling before guest execution.
The API thread, main thread, and each vCPU thread receive their own KillThread-mode allowlist. A disallowed syscall terminates the thread that issued it.
A client can reach a FlashVM socket only when the operating system has granted access. FlashVMM does not add another credential layer.
Allowed syscalls are checked against audit evidence that identifies the signal and syscall number. That process has caught real omissions, including chmod in the filesystem path and io_uring_enter when batched storage was introduced.
Startup ordering is measured against thread creation so no worker can begin execution before the process has completed its capability drop.
A token or signed handshake would not strengthen the local boundary: any process able to read that credential would already have the filesystem access required to reach the socket. FlashVMM therefore relies on the boundary the host already enforces. The per-user registry directory is 0700; VM sockets are 0600, or restricted to a configured group. Operators can inspect the effective policy directly with ls -la.