Skip to content
/linux-syscalls

Espacios de nombres y Contenedores · 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)97—sys_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