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
| Name | What it does |
|---|---|
| CLONE_NEWNSLinux 2.4.19 | New mount namespace; the caller gets a private copy of the mount table. |
| CLONE_NEWUTSLinux 2.6.19 | New UTS namespace; hostname and domainname changes are private. |
| CLONE_NEWIPCLinux 2.6.19 | New IPC namespace; SysV IPC objects and POSIX message queues are isolated. |
| CLONE_NEWNETLinux 2.6.24 | New network namespace; private network stack, interfaces, routing tables. |
| CLONE_NEWPIDLinux 3.8 | New 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.8 | New user namespace; unprivileged processes may call this and then write uid_map/gid_map to appear as root inside. |
| CLONE_NEWCGROUPLinux 4.6 | New cgroup namespace; the caller sees its current cgroup as root. |
| CLONE_NEWTIMELinux 5.6 | New time namespace; CLOCK_MONOTONIC and CLOCK_BOOTTIME can be offset independently. |
Errors you will actually hit
| errno | Meaning |
|---|---|
| EPERM | Caller lacks CAP_SYS_ADMIN (or, for CLONE_NEWUSER, the unprivileged_userns_clone sysctl is 0). |
| EINVAL | Unknown flag, or CLONE_NEWUSER requested with a multithreaded process. |
| ENOMEM | Insufficient kernel memory to create the namespace. |
| ENOSPC | The 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
Version numbers are read off the cited man pages, not memory. Spot one that's wrong? Tell Rod.
