Skip to content

Feature request: a public API to defer a Sandbox's COW commit/abort decision past process exit #215

Description

@rotep

Summary

We're building an MCP (Model Context Protocol) tool-call proxy on top of sandlock-core that wants to run a tool call inside a Sandbox, capture what it would change, hold that off disk pending an external approval decision (e.g. a human or policy approving/denying the effect), and only then commit or discard it. Today there's no supported way to do this once the sandboxed process has exited.

What exists today

  • Sandbox::on_exit / Sandbox::on_error (BranchAction::{Commit, Abort, Keep}) are consulted synchronously in Sandbox::drop, based on the child's exit status (crates/sandlock-core/src/sandbox.rs:2443). The decision has to be picked before the sandbox is dropped, and dropping is the only mechanism that fires it.
  • BranchAction::Keep doesn't hand back a resumable handle — it calls cow.keep() (sandbox.rs:2456), which is SeccompCowBranch::keep (cow/seccomp.rs:2215, pub(crate)), so the branch's own Drop backstop leaves the upper directory on disk instead of deleting it as an undisposed leak. The SeccompCowBranch itself is then dropped along with the rest of the Sandbox's internal Runtime when Sandbox::drop returns.
  • recovery::{list_preserved, read_preserved} can find and read that leftover PreservedBranch later (paths, a deleted list, pid), but the module's own doc comment says it's "report-only today — the supported route to finish an interrupted merge is to re-run commit() on the branch." That commit() is SeccompCowBranch::commit (cow/seccomp.rs:1760, pub fn), but it's unreachable from outside the crate because the containing module is pub(crate) mod cow; (lib.rs:21) and SeccompCowBranch is never re-exported anywhere.

Net effect: once a Sandbox producing a COW branch has exited, there's no public path to hold its change set open and later programmatically commit or abort it based on a decision made after that point — only report on where it landed on disk.

What would help

Something like a way to take the pending branch out of a Sandbox before/instead of letting Drop decide — e.g. a method that hands back a Send-safe handle exposing commit() / abort(), so the decision can be resolved later (after an async wait for external input) instead of being required synchronously at process-exit time. Even a minimal version scoped to the single-sandbox case (independent of the multi-stage transaction work in #65) would unblock our use case.

Happy to sketch a concrete API proposal or take a swing at a PR if there's appetite — wanted to check feasibility/direction first, since this touches Drop semantics and the COW internals directly.

Context

We depend on sandlock-core (pinned by commit) from KYOKAOS, a capability sandbox for MCP agents. The full investigation (including the source references above) is written up in ADR-0012 if useful context.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions