feat(box): --cap-add for fine-grained capability control#597
Draft
G4614 wants to merge 2 commits into
Draft
Conversation
e3f9692 to
d2cc206
Compare
Repeatable `--cap-add CAP` flag adds individual Linux capabilities to the container. "ALL" grants every cap. CAP_SYS_ADMIN triggers cgroup2 rw mount automatically. Wired end-to-end: CLI → BoxOptions.added_caps → proto → guest OCI spec. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
cap-add's ALL expansion was a no-op: build_capabilities double-prefixed
cap names (format!("CAP_{name}") over capability_names(), which already
returns "CAP_*"), so every Capability::from_str("CAP_CAP_*") errored and
the container silently kept only the 14-cap default set — missing
SYS_ADMIN/NET_ADMIN that privileged workloads need. Replace the broken
loop with all_capabilities() enumerating all 41 OCI capabilities.
Privileged containers (cap-add ALL/SYS_ADMIN) also need a writable
/proc/sys: dockerd writes net.ipv4.ip_forward to bring up its bridge.
LinuxBuilder otherwise defaults readonlyPaths/maskedPaths to the OCI
lists, which remount /proc/sys read-only — override them with empty sets
when privileged (matching `docker --privileged`). Non-privileged boxes
keep the protective defaults.
Together these let `boxlite run --kernel net --cap-add ALL docker:dind`
start dockerd end-to-end: Daemon initialized, API listening on
/var/run/docker.sock, `docker version` client+server, overlayfs storage,
cgroup v2. Adds guest unit tests for both (all_capabilities superset,
ALL effective set includes SYS_ADMIN/NET_ADMIN, privileged spec clears
readonly/masked paths while non-privileged keeps /proc/sys read-only).
Also rustfmt the kernel-net build.rs constants/Fetcher calls, committed
unformatted in the kernel-selection commit, so the branch passes fmt.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds a repeatable
--cap-add <CAP>flag for fine-grained Linux capabilities.ALLgrants the full 41-cap OCI set. Beyond the capability list, grantingSYS_ADMIN/ALLflips the container into the privileged shape that workloads like dockerd need:cgroup2mount at/sys/fs/cgroup(so dockerd can manage cgroups), and/proc/sys—build_linux_specclears the OCI defaultreadonlyPaths/maskedPathsso dockerd can writenet.ipv4.ip_forwardto bring up its bridge (matchingdocker --privileged).This PR is capability control only — no kernel selection (that lives in #596). Running docker-in-docker therefore needs #596 stacked: #596 supplies the
--kernel netblob with netfilter/iptables; #597 supplies the caps + privileged mounts//proc/sys. With both,boxlite run --kernel net --cap-add ALL docker:dindstarts dockerd end-to-end.Test plan
Unit tests on the cap → spec boundary:
cli.rs:cap_add_propagates_to_options,cap_add_all_propagates,no_cap_add_leaves_empty—--cap-addreachesBoxOptions.added_caps.spec.rs:build_capabilities_all_grants_dangerous_caps— theALLeffective set includesSYS_ADMIN/NET_ADMIN. Regression guard: the originalALLbranch double-prefixed cap names (CAP_CAP_*), so every insert errored andALLsilently degraded to the 14-cap default — missing exactly the caps dockerd needs.spec.rs:privileged_linux_spec_clears_readonly_and_masked_paths— privileged clears the/proc/syshardening; non-privileged keeps the OCI defaults.Verified on this host:
cargo nextest run -p boxlite-guest(cap/spec tests) +-p boxlite-cli(cap tests) — pass.make fmt:check:rust+cargo clippy --all-targets -- -D warnings— clean.make libkrunfw-netblob):boxlite run --kernel net --cap-add ALL docker:dind→ dockerd reachesDaemon has completed initialization+API listen on /var/run/docker.sock;docker versionshows client+server,docker infoshows overlayfs storage + cgroup v2.Before,
--cap-add ALLwas a no-op (the double-CAP_prefix dropped every cap) and/proc/sysstayed read-only, so dockerd couldn't start. After, full caps + writable/proc/sys+ cgroup-rw let dind run — once #596's net kernel is stacked underneath.🤖 Generated with Claude Code