$RodHat_
Syscall reference · Processes

unshare(2)

Create new namespaces and move the calling process into them without forking.

Since
Linux 2.6.16check your kernel →
glibc
glibc 2.14
System
Linux
Man page
unshare(2)

Synopsis

#define _GNU_SOURCE
#include <sched.h>

int unshare(int flags);

Rod's take

unshare(CLONE_NEWPID) does not move the caller into the new PID namespace. The caller stays where it is. The next fork creates a child that sees itself as PID 1. This surprises everyone once. Mount a new /proc before anything tries to read it. CLONE_NEWUSER is the exception to the CAP_SYS_ADMIN rule: unprivileged processes can create user namespaces, write uid_map and gid_map, and own root inside; this is rootless containers. FreeBSD's jail does the same job with one call and fewer footguns, but you can't compose namespace types independently. The composability is both the feature and the reason container runtimes are thousands of lines of C.

Flags and arguments that matter

NameWhat it does
CLONE_NEWNSLinux 2.4.19New mount namespace; the caller gets a private copy of the mount table.
CLONE_NEWUTSLinux 2.6.19New UTS namespace; hostname and domainname changes are private.
CLONE_NEWIPCLinux 2.6.19New IPC namespace; SysV IPC objects and POSIX message queues are isolated.
CLONE_NEWNETLinux 2.6.24New network namespace; private network stack, interfaces, routing tables.
CLONE_NEWPIDLinux 3.8New PID namespace for future children only. The caller stays in its original namespace; the next forked child becomes PID 1 in the new namespace.
CLONE_NEWUSERLinux 3.8New user namespace; unprivileged processes may call this and then write uid_map/gid_map to appear as root inside.
CLONE_NEWCGROUPLinux 4.6New cgroup namespace; the caller sees its current cgroup as root.
CLONE_NEWTIMELinux 5.6New time namespace; CLOCK_MONOTONIC and CLOCK_BOOTTIME can be offset independently.

Errors you will actually hit

errnoMeaning
EPERMCaller lacks CAP_SYS_ADMIN (or, for CLONE_NEWUSER, the unprivileged_userns_clone sysctl is 0).
EINVALUnknown flag, or CLONE_NEWUSER requested with a multithreaded process.
ENOMEMInsufficient kernel memory to create the namespace.
ENOSPCThe per-user or system-wide namespace limit has been reached.

Example

#define _GNU_SOURCE
#include <sched.h>
#include <err.h>

/* private mount and UTS namespaces */
if (unshare(CLONE_NEWNS | CLONE_NEWUTS) < 0)
    err(1, "unshare");

/* PID namespace: caller stays in parent ns; child is PID 1 */
if (unshare(CLONE_NEWPID) < 0)
    err(1, "unshare NEWPID");
pid_t child = fork();
if (child == 0) {
    /* PID 1 in new namespace; mount /proc before any ps(1) */
    mount("proc", "/proc", "proc", 0, NULL);
    execvp(argv[0], argv);
}

Trimmed from the full walkthrough in setns and unshare: moving between Linux namespaces.

BSD equivalent

FreeBSD: jail(2) (FreeBSD 4.0) wraps filesystem, network, and PID visibility in one coarser-grained call. OpenBSD: none; isolation is pledge(2), unveil(2), and chroot(2).

The long version, from the console

Sources

  1. unshare(2), man7.org
  2. setns(2), man7.org
  3. jail(2), FreeBSD

Version numbers are read off the cited man pages, not memory. Spot one that's wrong? Tell Rod.