Files
shadow/docker
Pierre Warnier aa987bb390 newuidmap, newgidmap: set the id maps of a user namespace (#298)
The setuid helpers that write /proc/<pid>/uid_map and gid_map: what Podman
and rootless Docker call for every container they start. The kernel lets an
unprivileged process map exactly one id into a namespace it created, its
own; everything a container needs beyond that takes the privilege these
carry, and they hand it out only within the ranges /etc/subuid and
/etc/subgid grant the caller. Fedora ships them in shadow-utils; with these
two, every tool the two reference distributions ship from the suite exists
here.

What is checked before anything is written was established by running the
GNU helpers against a real user namespace, never by reading them: the
operands must be a target and plain-decimal triples, a zero count is the
overflow message; every outside range must sit inside one granted range --
an entry by login name or by numeric uid -- or be the caller's own id mapped
once; root is exempt from neither, as newuidmap(1) says; and the target
process must belong to the caller by real uid, account uid and the owner of
/proc/<pid>, with all three named when they disagree. Overlapping ranges are
refused by name; the kernel would refuse them with a bare EINVAL, so the
message costs nothing and changes no accepted outcome.

The map file is opened through a descriptor held on /proc/<pid>, so a pid
recycled between the check and the write cannot redirect it, and the
`fd:N` form takes such a descriptor from a caller that did its own checks.
It is re-opened through /proc/self/fd rather than adopted, which keeps the
tool free of unsafe.

The tests do the real thing. A test user creates a namespace with unshare
and the helper runs as that user, unprivileged, against it: the own-id
mapping lands and the kernel's uid_map reads it back, the second write is
refused by the kernel and reported, the fd form works, and every refusal is
checked against the same live target. That runs on glibc and musl alike.

The Debian image gains the uidmap package so tests/gnu-compat.sh can hold
the helpers against GNU's. They take no --help -- any bad command line is
the usage text and exit 1 -- so the comparison is on the refusals the two
share rather than on help.

Verified: make check clean with the unprivileged run; 912 tests on alpine
and 934 on fedora with PAM; 393 e2e assertions against a real install, the
kernel-visible writes included; 57 GNU comparisons; 34 arm64 assertions
under emulation.
2026-09-07 15:46:36 +02:00
..