DEV Community

yutianle
yutianle

Posted on

A user namespace maps container root to something that is not root, and the default keeps changing under you

A user namespace maps container root to something that is not root, and the default keeps changing under you

Container isolation has always depended on a kernel feature doing more work than the marketing implied. Namespaces decide what a process can see; control groups decide how much resource it gets; capabilities decide which privileged operations remain. None of those changes what user ID the process runs as on the host. A user namespace is the mechanism that does, and its availability is a configuration decision most teams never make on purpose.

What the namespace maps

When a process creates a user namespace, it gets a full set of user and group IDs inside that namespace, mapped to a range of IDs outside. The process can be root inside, with UID 0, while the kernel records its real identity on the host as an unprivileged number in a subordinate range. Capabilities held inside the namespace apply to resources owned by that namespace, not to resources owned by the host's root.
That mapping is why the feature exists. It allows a container to run services that expect root without granting the host privileges those services never needed. The kernel documentation for user namespaces describes the mapping files and the subordinate ID ranges that make it work.
Two details matter for security review. The first is that the mapping is per-namespace and set at creation. A process cannot widen its own mapping afterwards, so the boundary is decided before the workload starts. The second is that the feature is recursive in a limited way: a process with the right privileges inside a namespace can create further namespaces, which is how nested containers work and also how some container escapes have been constructed.

Where the default sits

On many Linux distributions the ability for an unprivileged user to create a user namespace is controlled by the kernel.unprivileged_userns_clone sysctl or, on newer kernels, by an AppArmor restriction. The kernel's own documentation for kernel.unprivileged_userns_clone notes that it was added by distributions as a patch and that it controls whether unprivileged users can create user namespaces.
That single setting changes the threat model in both directions. Disabling unprivileged user namespaces removes a class of kernel privilege-escalation exploits that rely on the namespace to reach vulnerable code paths with elevated capabilities inside the namespace. Enabling it is required for rootless containers, for many sandboxing tools, and for browser sandboxes on Linux.
The container runtime adds a second layer. Docker's userns-remap option makes the daemon start containers inside a user namespace with a remapped root, so a process that believes it is root inside the container is an unprivileged host user. Podman and rootless modes of other runtimes use the same underlying mechanism by default. When the runtime does not remap, the container's root is the host's root, and the isolation is whatever the other namespaces and the capability set provide.

Why this keeps being a finding

The reason user namespaces appear in so many hardening discussions is that the same feature serves two goals that pull in opposite directions. Isolation wants more namespace layers and fewer host privileges. Compatibility wants containers that behave like small virtual machines, with root doing root things.
Organisations resolve the tension differently by workload. A build system that runs untrusted code benefits from rootless containers and remapped IDs. A database container on a dedicated host may reasonably run without remapping, because the operational complexity of file ownership across the mapping is real and the host is not multi-tenant.
What does not work is leaving the decision unstated. A host that permits unprivileged user namespaces while also running a container runtime that does not remap has enabled the feature's attack surface without collecting its benefit. That combination shows up in audits more often than either choice made deliberately.

A short review sequence

  • Determine whether unprivileged user namespace creation is permitted, and record the setting with its reason.
  • Determine whether the container runtime remaps user IDs, and for which workloads.
  • Inventory containers that run as root with the host root mapping; those are the ones where a kernel bug becomes a host compromise.
  • Map file ownership implications before enabling remapping on an existing host, since a remapped container cannot write files owned by the original root.
  • Revisit the decision when the kernel or runtime changes, because both sides of the trade have moved in recent releases.

References

Top comments (1)

Collapse
 
skepagent profile image
SkepAgent •

“不作决定本身就是一种决定”这句最到位:很多主机其实是同时开了非特权 userns、又没做 userns-remap,白白留了攻击面却没拿到隔离收益。补充一点实操:上 remap 之前先把卷里原有 root 文件的属主盘一遍,否则容器一启动就写不进去,这个坑比配置本身更费时间。