Namespaces & Containers · Section 2
unshare(2)
Disassociate parts of the calling process's execution context — namespaces, fs, files — without forking.
Signature
#include <sched.h>
int unshare(int flags);- flags
- Bitwise OR of CLONE_* flags. Each flag detaches the corresponding resource. CLONE_NEWUSER is special: it can be requested by unprivileged callers (subject to kernel config), and once granted, the caller has CAP_SYS_ADMIN inside the new namespace — enabling the other CLONE_NEW* requests.
Description
unshare() lets a process detach selected resources from its parent context without going through clone(). flags is a bitmask of CLONE_* values: CLONE_NEWUSER creates a new user namespace, CLONE_NEWNET a new network namespace, CLONE_NEWNS a new mount namespace, CLONE_NEWPID a new PID namespace (effective for the *next* child), CLONE_NEWUTS / CLONE_NEWIPC / CLONE_NEWCGROUP / CLONE_NEWTIME for the rest, and CLONE_FILES / CLONE_FS / CLONE_SYSVSEM for the non-namespace resources. unshare() is the inverse of inheritance: rather than 'create a child that doesn't share X', it says 'stop sharing X with anyone'. It is the primary primitive of the unshare(1) command-line tool and of rootless container construction.
Architecture mapping
| Architecture | Number | ABI | Entry point |
|---|---|---|---|
| x86 (i386) | 310 | i386 | sys_unshare |
| x64 (x86_64) | 272 | common | sys_unshare |
| ARM64 (aarch64) | 97 | — | sys_unshare |
Kernel history
Introduced in Linux 2.6.16.
2.6.16
unshare() was added in 2.6.16 alongside the namespace family. Originally it supported CLONE_FILES, CLONE_FS, CLONE_NEWNS, CLONE_SYSVSEM only; subsequent kernels added each new namespace as a flag.
3.8
CLONE_NEWUSER landed (Linux 3.8), making rootless containers possible. The kernel's user-namespace UID/GID mapping mechanism arrived with it; the canonical unprivileged-container pattern is unshare(CLONE_NEWUSER|CLONE_NEWNS|…) then write /proc/self/uid_map.
4.6
CLONE_NEWCGROUP was added — process can have a virtualised view of /proc/self/cgroup, used by nested-cgroupv2 container hierarchies.
seccomp & containers
Docker default profile
Blocked
Podman default profile
Blocked
unshare() is BLOCKED by default in Docker and Podman because allowing it within a container lets the workload create nested namespaces — the foundation of nested-container exploits and a CVE-rich path. Enable it explicitly only for containers that legitimately host nested runtimes (Docker-in-Docker, Kubernetes-in-Kubernetes). Argument filtering to deny CLONE_NEWUSER specifically is a tighter alternative that allows other unshare uses while blocking the user-namespace escalation path.
libseccomp
// unshare() is NOT on the Docker default allow-list. Explicitly deny.
seccomp_rule_add(ctx, SCMP_ACT_ERRNO(EPERM), SCMP_SYS(unshare), 0);strace example
$ strace -e unshare unshare -U -r /bin/whoami 2>&1 | head -3
unshare(CLONE_NEWUSER) = 0unshare() in strace shows the flag bitmask symbolically. The classic 'I want to test as root' pattern is unshare(CLONE_NEWUSER) followed by a write to /proc/self/uid_map — visible directly. For ip netns add commands you'll see unshare(CLONE_NEWNET) then bind-mounts to /run/netns/<name>.
Security & observability
unshare(CLONE_NEWUSER) is the entry point of unprivileged-userns privilege-escalation chains — historically several CVEs (CVE-2018-18955, CVE-2022-0185, CVE-2022-2588) gave root via user-namespace constructs. The mitigation is sysctl kernel.unprivileged_userns_clone=0 on hardened hosts; Debian / Ubuntu often enable this. eBPF tracepoint sys_enter_unshare with the flags decoded gives complete observability; a container workload calling unshare(CLONE_NEWUSER|…) is rare and worth alerting on. From inside, /proc/self/ns/* readlinks expose the current namespace inode numbers — compare against the container's expected namespaces to detect drift.
Errors
- EINVAL
- Bad combination of flags, or flag not supported on this kernel.
- ENOMEM
- Insufficient kernel memory.
- ENOSPC
- —
- EPERM
- Caller lacks CAP_SYS_ADMIN for one of the requested namespaces (everything except CLONE_NEWUSER on systems where unprivileged userns is enabled). On Debian with kernel.unprivileged_userns_clone=0, even CLONE_NEWUSER fails with EPERM for non-root.
- EUSERS
- The nested-user-namespace depth would exceed MAX_USER_NAMESPACE_LEVEL (32).
Flags
- CLONE_FILES
- 0x00000400
- Disassociate the file descriptor table. After unshare(CLONE_FILES), opening or closing a fd in this process doesn't affect siblings that previously shared the table (e.g. via clone(CLONE_FILES)).
- CLONE_FS
- 0x00000200
- —
- CLONE_NEWCGROUP
- 0x02000000
- New cgroup namespace. The process's /proc/self/cgroup view is rebased — useful for nested containerisation.
- CLONE_NEWIPC
- 0x08000000
- —
- CLONE_NEWNET
- 0x40000000
- New network namespace. Empty network state (no interfaces other than lo). Used by container runtimes and by ip netns.
- CLONE_NEWNS
- 0x00020000
- New mount namespace. Subsequent mount() / umount() calls are local to this namespace. The basis of MS_PRIVATE root and rootless mounts.
- CLONE_NEWPID
- 0x20000000
- New PID namespace. The next child created via fork()/clone() becomes PID 1 in the new namespace; the calling process itself remains in the old namespace.
- CLONE_NEWTIME
- 0x00000080
- —
- CLONE_NEWUSER
- 0x10000000
- New user namespace. Available to unprivileged callers and the foundation of rootless containers. Inside the new userns the caller can map a single UID/GID pair and gain CAP_SYS_ADMIN, which unlocks the other namespace creations.
- CLONE_NEWUTS
- 0x04000000
- —
- CLONE_SYSVSEM
- 0x00040000
- —