Subject: boxr 0.1.55, a rootless container runtime. This write-up is independent analysis, not upstream work.
The symptom
A rootless container started, but it had no eth0:
ip: can't find device 'eth0'
nslookup: can't connect to remote host (192.168.1.1): Network unreachable
The host was SELinux-enforcing. Podman ran the same rootless pasta setup without trouble, so the network was not the problem.
What I ruled out
- DNS. The container had resolv.conf entries; the interface was missing before DNS mattered.
- Capabilities. The parent was unprivileged, but granting it capabilities did not help. The denial was not a capability check.
- Pasta itself. Pasta worked under Podman on the same host, so the binary and the host policy were fine.
The actual denial
The runtime started pasta from the unprivileged parent after the child had unshared its network namespace. Pasta ran as pasta_t and tried to open /proc/<child>/ns/net. That file belonged to the unprivileged user, and SELinux denied the open. Pasta exited before configuring the interface.
Two implementation details made it silent:
- The spawn result was ignored, so a failed pasta process looked like a successful one.
- Pasta’s stdout and stderr were discarded, so the denial never reached the terminal.
The fix
Run 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 is allowed to open the bind-mounted user_tmp_t file, so the fix needs no host policy change and no disabled SELinux. IP, ICMP, DNS, HTTP/HTTPS, and published TCP ports all worked.
What I would change in the runtime
- Surface the spawn failure instead of treating it as an optional feature.
- Keep pasta’s stderr when the interface fails to come up.
- Treat “no eth0 after network setup” as a hard error, not a container that happens to start.
The full write-up and benchmarks are in the project page.