Skip to content

Implement bubblewrap for lightweight process container on Linux#314

Merged
kanismohammed merged 6 commits into
mainfrom
user/shschaefer/bubblewrap
May 21, 2026
Merged

Implement bubblewrap for lightweight process container on Linux#314
kanismohammed merged 6 commits into
mainfrom
user/shschaefer/bubblewrap

Conversation

@shschaefer

@shschaefer shschaefer commented May 14, 2026

Copy link
Copy Markdown
Collaborator

Implement bubblewrap for lightweight process container on Linux.

📖 Description

This adds support for the Bubblewrap based process container on Linux.

🔍 Validation

The full PR will have complete validation tests.

✅ Checklist

📋 Issue Type

  • Bug fix
  • Feature
  • Task
Microsoft Reviewers: Open in CodeFlow

Copilot AI review requested due to automatic review settings May 14, 2026 18:25

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

Note

Copilot was unable to run its full agentic suite in this review.

Adds a feasibility/implementation plan document for introducing a Bubblewrap (bwrap) backend as a lightweight Linux process container for MXC.

Changes:

  • Adds a new design/feasibility evaluation document describing a Bubblewrap backend architecture
  • Outlines planned schema/model/parser updates, a new bwrap_common crate, and SDK/platform detection changes
  • Documents intended policy mappings (filesystem/network) and proposed test additions
Show a summary per file
File Description
docs/bwrap-support/bubblewrap-backend-plan.md New planning document describing approach, integration points, and test/docs follow-ups for a Bubblewrap backend

Copilot's findings

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

Comment on lines +31 to +40
| Aspect | LXC | Bubblewrap |
|--------|-----|------------|
| Privileges | Root required | Unprivileged (user namespaces) |
| Rootfs | Downloads distro rootfs | Bind-mounts host filesystem |
| Startup | Create → Start → Attach | Single `bwrap` exec |
| Network isolation | iptables + veth | `--unshare-net` (no network stack) |
| Network filtering | Per-host allow/block via iptables | `--unshare-net` for full block; iptables (reuses `NetworkIptablesManager`) for per-host filtering |
| Filesystem policy | LXC mount entries | `--ro-bind`, `--bind`, `--tmpfs` |
| Signal cleanup | Kill container on SIGTERM | Process dies with parent |
| Dependencies | `lxc-*` tools, rootfs templates | Single `bwrap` binary |
Comment on lines +56 to +59
No backend-specific config block for now. Bubblewrap will use only the shared
cross-backend fields (`filesystem`, `network`, `process`, `lifecycle`, `ui`). Backend-specific
knobs (e.g., namespace sharing, device bindings) can be added later under `experimental.bubblewrap`
if needed.
Comment on lines +72 to +74
No `BubblewrapConfig` struct needed for now — the runner uses only the shared
`ContainerPolicy` fields on `CodexRequest` (filesystem paths, network policy, env, etc.).
A backend-specific config can be added later under `ExperimentalConfig` if needed.
Comment on lines +339 to +343
- `src/wxc_common/src/models.rs` — add `Bubblewrap` variant, `BubblewrapConfig` struct, wire into `ExperimentalConfig` and `CodexRequest`
- `src/wxc_common/src/config_parser.rs` — add `RawBubblewrap`, parsing, containment match arm

### Schema (modify)
- `schemas/dev/mxc-config.schema.0.6.0-dev.json` — add `"bubblewrap"` to enum, add config block
Comment on lines +339 to +343
- `src/wxc_common/src/models.rs` — add `Bubblewrap` variant, `BubblewrapConfig` struct, wire into `ExperimentalConfig` and `CodexRequest`
- `src/wxc_common/src/config_parser.rs` — add `RawBubblewrap`, parsing, containment match arm

### Schema (modify)
- `schemas/dev/mxc-config.schema.0.6.0-dev.json` — add `"bubblewrap"` to enum, add config block
@@ -0,0 +1,358 @@
# Bubblewrap (bwrap) Backend for MXC — Feasibility Evaluation
| Network isolation | iptables + veth | `--unshare-net` (no network stack) |
| Network filtering | Per-host allow/block via iptables | `--unshare-net` for full block; iptables (reuses `NetworkIptablesManager`) for per-host filtering |
| Filesystem policy | LXC mount entries | `--ro-bind`, `--bind`, `--tmpfs` |
| Signal cleanup | Kill container on SIGTERM | Process dies with parent |
//! spawns the `bwrap` binary.

pub mod bwrap_command;
pub mod bwrap_runner;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

bwrap_runner

does this need conditional compilation? "#[cfg(target_os = "linux")]"

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.

Yes — I gated bwrap_runner at the module export with #[cfg(target_os = "linux")] in src/bwrap_common/src/lib.rs so only Linux builds include it. Addressed in bed4be3.

jsidewhite
jsidewhite previously approved these changes May 15, 2026

@jsidewhite jsidewhite left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

:shipit:

@huzaifa-d

Copy link
Copy Markdown
Contributor

@copilot resolve the merge conflicts in this pull request

Copilot AI commented May 18, 2026

Copy link
Copy Markdown
Contributor

@copilot resolve the merge conflicts in this pull request

Merge conflicts are resolved by merging origin/main into this branch and fixing the workspace conflict in src/Cargo.toml. Addressed in bed4be3.

Copilot AI requested a review from huzaifa-d May 18, 2026 18:32
@SohamDas2021

Copy link
Copy Markdown
Contributor

Found the following while manually testing the runtime end-to-end. build_args in bwrap_command.rs emits arguments in this order:

  1. --ro-bind / / (base)
  2. policy mounts: --bind / --ro-bind / --tmpfs for the user's readwritePaths / readonlyPaths / deniedPaths
  3. --dev /dev, --proc /proc, --tmpfs /tmp

Because bwrap applies mounts in order with later mounts overriding at the same path, step 3's hard-coded --tmpfs /tmp obscures all the subdirs; in every policy mount in step 2 whose target lives under /tmp - /tmp/, /tmp/, /tmp/ all disappear inside the sandbox.

Repro

mkdir -p /tmp/bwrap-rw /tmp/bwrap-ro /tmp/bwrap-denied
echo "from host" > /tmp/bwrap-ro/test.txt
echo "secret" > /tmp/bwrap-denied/secret.txt

cat > /tmp/repro.json <<'JSON'
{
"version": "0.6.0-alpha",
"containment": "bubblewrap",
"platform": "linux",
"process": {
"commandLine": "cat /tmp/bwrap-ro/test.txt; echo X > /tmp/bwrap-rw/output.txt"
},
"filesystem": {
"readonlyPaths": ["/tmp/bwrap-ro"],
"readwritePaths": ["/tmp/bwrap-rw"],
"deniedPaths": ["/tmp/bwrap-denied"]
}
}
JSON

src/target/release/lxc-exec --experimental /tmp/repro.json

Observed:

cat: /tmp/bwrap-ro/test.txt: No such file or directory
sh: 1: cannot create /tmp/bwrap-rw/output.txt: Directory nonexistent

Expected: the RO bind serves the file; the RW write succeeds and lands on the host.

I will push out the fix.

@shschaefer shschaefer marked this pull request as ready for review May 20, 2026 17:36
@shschaefer

Copy link
Copy Markdown
Collaborator Author

@copilot resolve the merge conflicts in this pull request

@jsidewhite jsidewhite dismissed their stale review May 20, 2026 21:40

revoking review

@kanismohammed kanismohammed merged commit ad67607 into main May 21, 2026
18 checks passed
@kanismohammed kanismohammed deleted the user/shschaefer/bubblewrap branch May 21, 2026 00:30
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.

7 participants