bug(docker): snapshots of gVisor (runsc) sandboxes silently drop all writes under runsc's default --overlay2=root:self
What happened
Forking a child from a live Docker-backed sandbox can come back missing files that exist on the
parent's live filesystem at fork time — in our repro, a globally npm install -g'd CLI binary.
The snapshot/commit and the resulting fork both report success; nothing surfaces the missing
files anywhere.
Repro (no OpenSandbox code involved — bare docker commit)
docker exec <container> npm install -g <pkg>
docker exec <container> which <pkg-bin> # present, works
docker commit <container> test-image
docker run --rm test-image which <pkg-bin> # ABSENTThis reproduces on a single, solo commit — no concurrent commit anywhere near it, no retries,
nothing racing. We confirmed via Alineo.spawn()/fork(), which calls
POST /v1/sandboxes/{id}/snapshots and restores from it, and independently via a bare docker commit of the same container outside any OpenSandbox code path — same result both times.
Ruled out:
- Hardlinks — every file under the missing package's tree has a link count of 1.
- A separate mount/volume —
docker inspect --format '{{json .Mounts}}'is[],.Config.Volumesisnull, and the missing directory's device number matches every other directory under the same parent path (including a sibling package directory that does survive the commit). - Concurrency — reproduces on a solo commit with nothing else in flight. (We originally
suspected two simultaneous
fork()calls against one sandbox as the trigger — see "Related" — but the same corruption occurs with only ever one commit in flight, so that wasn't it.)
Environment
Docker runtime, overlayfs storage driver, kernel 6.19.14-108.fc42.x86_64 (Fedora 42),
execd_image v1.0.19/v1.0.22, runsc (gVisor) as the sandbox's own container runtime.
Impact
Any workflow that installs something into a sandbox and then forks it (e.g. alineo's RLM
fan-out, where a parent installs a CLI/dependency once and forks multiple children from it) can
silently produce children missing that install, with no error at any layer — the fork, the
snapshot, and the restore all report success.
Related
Also worth closing regardless of the above: the Docker runtime's createSnapshot() has no
concurrency guard — two simultaneous POST .../snapshots against the same sandbox are both
accepted, unlike the Kubernetes runtime, which explicitly rejects a second in-flight snapshot per
sandbox with 409. Not the cause of the corruption described above (confirmed reproducible on a
solo commit), but a separate, real gap in its own right — worth the same protection either way.
Source: opensandbox-group/OpenSandbox