Files
doos/docs/RESEARCH.md
T

3.0 KiB

Research: user-level containers with overlayfs

Measured on this machine: Ubuntu, kernel 7.0.0-38, AppArmor 5.0.2, slirp4netns 1.3.3, uid 1000, no root at runtime.

What works unprivileged

  1. clone(CLONE_NEWUSER|NEWNS|NEWPID|NEWUTS|NEWIPC[|NEWNET]), then the parent writes setgroups=deny, uid_map, gid_map (single entry, own uid). No setuid helpers (newuidmap) needed.
  2. overlayfs mounts inside the userns (kernel >= 5.11) with the userxattr option. Upper and work dirs must be on a filesystem with user xattrs (ext4, tmpfs >= 6.6 verified for ours).
  3. Mounts that work inside: tmpfs, proc (needs own pidns), devpts (new instance, no gid= since gid 5 is unmapped), bind mounts of host /dev/{null,zero,full,random,urandom,tty} (no mknod in a userns), read-only remount of /proc subpaths (must copy locked flags from statvfs).
  4. pivot_root(".", ".") plus lazy unmount of the old root.

What does not

  • Writing mapped uid ranges beyond own uid needs newuidmap + /etc/subuid. Skipped: single mapping keeps the design dumb. Consequence: no chown/su to other uids inside, so apt install as non-root users does not work.
  • cgroups: no memory/cpu/pid limits without systemd delegation. Not implemented (gap).
  • Ubuntu 24.04+: kernel.apparmor_restrict_unprivileged_userns=1 lets any binary create a userns but strips capabilities inside it. Measured: uid_map write succeeds, first mount fails with EPERM. Fix is an AppArmor profile granting userns to the binary (apparmor/doos, install once with sudo). Turning the sysctl off is global and weaker.

Networking options

Option Result
slirp4netns (chosen default) Works unprivileged. Needs only the netns of the child pid. --disable-host-loopback blocks the container from reaching host 127.0.0.1 (measured: blocked). DNS via 10.0.2.3 works (measured).
pasta Installed here but not used: slirp4netns suffices, one dependency.
veth + bridge Needs CAP_NET_ADMIN in the host netns. Not possible unprivileged.
host netns Works, zero isolation. Offered as explicit --net host.

Host safety design

  • No host paths writable: overlay lower dirs are only reachable through overlay (writes copy up to the container upper). Verified: write to /usr and /etc inside leaves host untouched.
  • Only /usr /etc /opt and compat dirs are exposed read-through. /home, /var, /sys, /root of the host are not present.
  • Old root detached after pivot, no_new_privs, /proc hardened, nosuid/nodev on tmpfs/devpts/overlay.
  • Residual exposure (gaps): host /etc is readable inside (any world-readable secret in it); abstract unix sockets are shared in --net host; no resource cgroups, so a container can fill the disk through its upper dir or fork-bomb within the user's RLIMIT_NPROC; kernel attack surface of userns is that of the host kernel.

Measurements (this machine, 5 sequential attach -- true)

Mode Per attach
slirp ~26 ms
none ~6 ms

Single run set, one machine; no other hardware measured.