Skip to content

BaseContainer: Ephemeral sandbox lifecycle cleanup (Part 1)#321

Merged
bbonaby merged 12 commits into
mainfrom
jsidewhite/mxc_lifecycle_cleanup_pr2
May 16, 2026
Merged

BaseContainer: Ephemeral sandbox lifecycle cleanup (Part 1)#321
bbonaby merged 12 commits into
mainfrom
jsidewhite/mxc_lifecycle_cleanup_pr2

Conversation

@jsidewhite

@jsidewhite jsidewhite commented May 15, 2026

Copy link
Copy Markdown
Member

BaseContainer: Ephemeral sandbox lifecycle tracking

Implements proper AppContainer profile cleanup for the BaseContainer runner when destroy_on_exit: true is configured.

What it does

  • Ephemeral identities: Every BaseContainer launch gets a unique sandbox-{random hex} identity, ensuring no profile collisions between concurrent sandboxes.
  • Registry tracking: Before launch, writes a tracking entry under HKCU\Software\Classes\Local Settings\Software\Microsoft\Windows\CurrentVersion\ProcessSandboxes\Mappings\{SID} with metadata (identity, SID, origin, requested identity, timestamps). A volatile Active subkey marks in-flight sandboxes for crash detection.
  • Cleanup on exit: ==FUTURE==
  • Deferred cleanup: If a network proxy is configured, cleanup is skipped (proxy state can't be torn down yet). A CleanupDeferred marker is written to the tracking entry for future tooling.
  • Ctrl+C handling: Registers a console control handler so ==FUTURE== cleanup still runs on interrupt.
  • No-op when destroy_on_exit: false: No tracking, no cleanup -- the profile persists across runs.

Why

Previously, BaseContainer never cleaned up AppContainer profiles. Over time this leaks registry state and BFS policies. This in the ==FUTURE== brings BaseContainer in line with LXC's existing cleanup behavior and follows the Tessera sandbox lifecycle spec.

This PR adds ephemeral sandbox lifecycle cleanup to the BaseContainer runner. When destroy_on_exit: true, each sandbox gets a unique random identity (sandbox-{hex}), a registry tracking entry under HKCU...\ProcessSandboxes\Mappings{SID} for crash recoverability. It also installs a Ctrl+C handler so cleanup runs on interrupt, and defers cleanup when a network proxy is active since proxy state can't yet be torn down.

Architecture

 ┌─────────────────────────────────────────────────────────┐
 │              base_container_runner.rs                    │
 │  (ScriptRunner::run_script)                             │
 │                                                         │
 │  1. Generate ephemeral identity ──┐                     │
 │  2. Derive SID                    │                     │
 │  3. Write tracking entry ─────────┼──► Registry         │
 │  4. Register Ctrl+C handler       │    (HKCU\...\       │
 │  5. CreateProcessInSandbox        │     Mappings\{SID}) │
 │  6. WaitForSingleObject           │                     │
 │  7. run_sandbox_cleanup() // FUTURE ────────┘                     │
 │       ├─► filesystem_bfs::clear_policy()                │
 │       ├─► DeleteAppContainerProfile()                   │
 │       └─► delete_tracking_key()                         │
 │                                                         │
 │  [proxy?] ──► mark_cleanup_deferred()                   │
 │  [Ctrl+C] ──► ctrl_handler() ──► cleanup or defer      │
 └─────────────────────────────────────────────────────────┘

Implements proper AppContainer profile cleanup for the BaseContainer runner when `destroy_on_exit: true` is configured.

### What it does

- **Ephemeral identities**: Every BaseContainer launch gets a unique `sandbox-{random hex}` identity, ensuring no profile collisions between concurrent sandboxes.
- **Registry tracking**: Before launch, writes a tracking entry under `HKLM\SOFTWARE\Microsoft\MxcSandbox\Tracking\{SID}` with metadata (identity, SID, origin, requested identity, timestamps). A volatile `Active` subkey marks in-flight sandboxes for crash detection.
- **Cleanup on exit**: After the sandboxed process exits, cleans up BFS filesystem policies (`bfscfg --removepolicy`) then deletes the AppContainer profile. Removes the tracking entry on success.
- **Deferred cleanup**: If a network proxy is configured, cleanup is skipped (proxy state can't be torn down yet). A `CleanupDeferred` marker is written to the tracking entry for future tooling.
- **Ctrl+C handling**: Registers a console control handler so cleanup still runs on interrupt.
- **No-op when `destroy_on_exit: false`**: No tracking, no cleanup -- the profile persists across runs.

### Why

Previously, BaseContainer never cleaned up AppContainer profiles. Over time this leaks registry state and BFS policies. This brings BaseContainer in line with LXC's existing cleanup behavior and follows the Tessera sandbox lifecycle spec.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings May 15, 2026 06:22
// Only runs when tracking was written (i.e., destroy_on_exit was true).
// Deferred if a network proxy is configured (proxy state can't be cleaned up yet).
if tracking_written {
run_sandbox_cleanup(

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

run_sandbox_cleanup

@bbonaby - do I need an RAII-like container for this cleanup in case someone early returns or an exception happens?

(early return on line 617, for example)

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot do i need to wrap run_sandbox_cleanup in an RAII-like type?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just seeing this but I believe so, for what it's worth you might be able to use the scopeguard crate: https://crates.io/crates/scopeguard like you would with wil::scope_exit

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds a Windows-only lifecycle tracking + cleanup mechanism for the BaseContainer backend to support lifecycle.destroy_on_exit: true, aiming to prevent long-term leaks of AppContainer profiles and BFS filesystem policy state.

Changes:

  • Added a new sandbox_tracking module that records per-sandbox tracking info in the registry, supports best-effort cleanup (BFS policy removal + AppContainer profile deletion), and installs a console control handler for interrupt cleanup.
  • Updated BaseContainerRunner to mint ephemeral sandbox-{hex} identities when destroy_on_exit is enabled, write a pre-launch tracking entry, and perform best-effort cleanup on exit/failure/interrupt.
  • Added FileSystemBfsManager::clear_policy to allow cleanup even when the BFS manager wasn’t previously “configured” within the current process.
Show a summary per file
File Description
src/wxc_common/src/sandbox_tracking.rs New registry-based tracking + cleanup helpers, plus Ctrl+C/console-close cleanup hook and unit tests.
src/wxc_common/src/lib.rs Exposes the new sandbox_tracking module on Windows builds.
src/wxc_common/src/filesystem_bfs.rs Adds clear_policy() helper to unconditionally clear BFS policy for an identity.
src/wxc_common/src/base_container_runner.rs Integrates ephemeral identity + tracking + cleanup into BaseContainer process launch and exit flow.

Copilot's findings

  • Files reviewed: 4/4 changed files
  • Comments generated: 7

Comment thread src/wxc_common/src/base_container_runner.rs
Comment thread src/wxc_common/src/base_container_runner.rs
Comment thread src/wxc_common/src/base_container_runner.rs Outdated
Comment thread src/wxc_common/src/sandbox_tracking.rs
Comment thread src/wxc_common/src/sandbox_tracking.rs Outdated
Comment thread src/wxc_common/src/sandbox_tracking.rs
Comment thread src/wxc_common/src/sandbox_tracking.rs Outdated
Comment thread src/wxc_common/src/sandbox_tracking.rs
Comment thread src/wxc_common/src/base_container_runner.rs Outdated
Comment thread src/wxc_common/src/base_container_runner.rs
Comment thread src/wxc_common/src/sandbox_tracking.rs Outdated
Comment thread src/wxc_common/src/base_container_runner.rs
Comment thread src/wxc_common/src/sandbox_tracking.rs Outdated
Comment thread src/wxc_common/src/sandbox_tracking.rs
Comment thread src/wxc_common/src/sandbox_tracking.rs Outdated
Comment thread src/wxc_common/src/sandbox_tracking.rs
@bbonaby bbonaby merged commit e67a471 into main May 16, 2026
17 checks passed
@bbonaby bbonaby deleted the jsidewhite/mxc_lifecycle_cleanup_pr2 branch May 16, 2026 01:18
@jsidewhite jsidewhite changed the title BaseContainer: Ephemeral sandbox lifecycle cleanup BaseContainer: Ephemeral sandbox lifecycle cleanup (Part 1) May 18, 2026
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.

4 participants