Skip to content

feat(check): support copy-on-write sandboxing on Linux#156

Merged
RobbieMcKinstry merged 1 commit into
trunkfrom
robbie/linux-sandboxing
Jul 3, 2026
Merged

feat(check): support copy-on-write sandboxing on Linux#156
RobbieMcKinstry merged 1 commit into
trunkfrom
robbie/linux-sandboxing

Conversation

@RobbieMcKinstry

Copy link
Copy Markdown
Contributor

Problem

select_sandbox() gated the real copy-on-write sandbox to target_os = "macos" and routed everything else — including Linux — to UnsupportedSandbox, which always errors. So multi check could not create a sandbox on Linux at all; every run failed before an agent could start.

Fix

A native Linux CoW sandbox, ReflinkSandbox (src/checks/sandbox/linux.rs):

  • Linux has no whole-tree clone syscall like macOS's clonefile(2), so it walks the tree, recreates directories/symlinks, and clones each regular file with the FICLONE ioctl — a reflink (metadata-only, copy-on-write share of the file's extents).
  • FICLONE only works on CoW filesystems (Btrfs, XFS reflink=1, bcachefs). On ext4/tmpfs/overlay it fails, so we fall back to a plain byte copy — the sandbox is always a fully independent clone, just without the space savings.
  • Permissions (incl. exec bits) preserved on both paths; symlinks recreated verbatim. The reflink path restores exact mode after cloning (the create goes through the umask).

Wiring (src/checks/sandbox/mod.rs): cfg selection is now macOS → clonefile, Linux → reflink, any other target → the erroring stub. The independence test now runs on Linux too.

CHECKS.md: the sandbox requirement is now Cross-Platform and Platform-Gated — it fails if a real sandbox is created on only one of macOS/Linux.

Validation

  • macOS: cargo make clippy + cargo make test (119 pass).
  • Linux (which CI actually compiles, and where macos.rs is not built): compiled the exact reflink logic in a Linux container — clippy-clean; fallback copy path verified on overlay fs; FICLONE success path verified on a real btrfs loopback (reflink OK per file). Independence, nested dirs, symlink preservation, exec-bit preservation, and RAII teardown all pass on both paths.

Note

Reflinks only engage when $TMPDIR and the working tree share the same CoW filesystem (same cross-volume constraint macOS clonefile has). Otherwise every file takes the correct-but-not-CoW copy fallback. A future tweak — placing the temp dir as a sibling of the source tree — would guarantee reflinks; left out of this PR to keep parity with the macOS implementation.

🤖 Generated with Claude Code

`select_sandbox()` gated the real CoW sandbox to macOS and routed every
other target — including Linux — to `UnsupportedSandbox`, which always
errored. `multi check` therefore could not create a sandbox on Linux at
all.

Add a native Linux implementation, `ReflinkSandbox`. Linux has no
whole-tree clone syscall like macOS's `clonefile`, so it recreates the
directory structure under a temp dir and clones each regular file with
the `FICLONE` ioctl (a reflink — a metadata-only, copy-on-write share of
the file's extents). `FICLONE` only works on CoW filesystems (Btrfs, XFS
with reflink=1, bcachefs); on others (ext4, tmpfs) it fails and we fall
back to a plain byte copy, so the sandbox is always an independent clone
— just without the CoW space savings. Permissions (incl. exec bits) are
preserved on both paths, and symlinks are recreated verbatim.

Wire it into the `cfg` selection (macOS → clonefile, Linux → reflink,
other → stub) and widen the independence test to run on Linux too.

Update CHECKS.md to require sandboxing on both macOS and Linux.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@RobbieMcKinstry RobbieMcKinstry force-pushed the robbie/linux-sandboxing branch from 8211a8b to 6b1ee8b Compare July 3, 2026 20:24
@RobbieMcKinstry RobbieMcKinstry added this pull request to the merge queue Jul 3, 2026
Merged via the queue into trunk with commit 6d77cff Jul 3, 2026
9 checks passed
@RobbieMcKinstry RobbieMcKinstry deleted the robbie/linux-sandboxing branch July 3, 2026 20:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant