Subject: boxr, a rootless container runtime. This page is an independent RCA, patch prototype, and benchmark of that upstream project — not an upstream contribution.
Problem
On an SELinux-enforcing Fedora/openSUSE host, boxr run --network pasta started a container with no eth0 and no network. The same host ran rootless pasta containers under Podman without trouble. The failure was silent: pasta’s stdout and stderr were discarded, and the parent ignored the spawn error.
Root cause
boxr started pasta from the unprivileged parent after the child unshared its network namespace. Pasta then ran as pasta_t and tried to open /proc/<child>/ns/net, a file owned by the unprivileged user. SELinux denied the open, so pasta exited before configuring the interface.
Giving the parent more capabilities did not help: the denial was a type transition and open check on the netns file, not a capability check.
Fix
The validated approach runs pasta inside the container’s user namespace, but outside its network namespace:
- After UID/GID mapping, fork a helper in the child user namespace before
unshare(CLONE_NEWNET). - In the helper, unshare a private mount namespace and bind-mount the child’s netns to a path under
$XDG_RUNTIME_DIR/boxr/netns/. - Start pasta with
--netns <path>and keep it in the foreground. - Clean up the bind mount on exit,
stop, andrm. - Add
--dns-forwardand prepend the DNS proxy to the container’sresolv.conf.
pasta_t can open the bind-mounted user_tmp_t file, so no host policy change is needed. IP, ICMP, DNS, HTTP/HTTPS, and published TCP ports all worked.
Benchmarks
I benchmarked a local boxr 0.1.53 build containing the fix against Podman 6.1.2 on a 4 vCPU / 3.9 GiB arm64 host. Five runs per case, medians:
| Case | boxr | Podman |
|---|---|---|
Cold pull, debian:bookworm-slim | 11.26 s | 18.68 s |
--no-cache build, Python service | 131.04 s | 52.93 s |
alpine true, no network | 0.120 s | 1.575 s |
boxr’s build was slower in wall time but used less CPU. The gap was not caused by base-image pulling: with an explicit pull before every build, Podman remained about 1.9x faster. boxr’s build used less process memory but much more transient system memory because its temporary rootfs copies landed on tmpfs. That is a concrete optimization target, not a reason to dismiss the runtime.
Limits
These numbers are from one host, with no CPU pinning or cache dropping. boxr 0.1.55 was not benchmarked because rootless pasta is broken there on this SELinux host. The results compare this workload on this machine; they are not a general ranking.
Credit
boxr is an upstream project by kchaitanya863. This work is an independent RCA, patch prototype, and benchmark; it is not an upstream contribution.