Skip to content
/linux-syscalls

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

ArchitectureNumberABIEntry point
x86 (i386)310i386sys_unshare
x64 (x86_64)272commonsys_unshare
ARM64 (aarch64)97sys_unshare

Kernel history

Introduced in Linux 2.6.16.

  1. 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.

  2. 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.

  3. 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)                  = 0

unshare() 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

Related syscalls