Namespaces & Containers · Section 2
setns(2)
Move the calling thread into an existing namespace identified by a file descriptor.
Signature
#include <sched.h>
int setns(int fd, int nstype);- fd
- Descriptor referring to a namespace. From /proc/<pid>/ns/<type>, or a pidfd (since 5.8).
- nstype
- 0 to accept any namespace type, or one of CLONE_NEWNS / CLONE_NEWUSER / CLONE_NEWPID / CLONE_NEWNET / CLONE_NEWUTS / CLONE_NEWIPC / CLONE_NEWCGROUP / CLONE_NEWTIME to require that specific type. The latter is the safer pattern.
Description
setns() reassociates the calling thread with the namespace referred to by fd. fd is typically obtained by open()ing one of the /proc/<pid>/ns/* files (mnt, pid, net, user, ipc, uts, cgroup, time) or by pidfd_open() + the new setns(pidfd, CLONE_NEW*) form (Linux 5.8+). nstype is either 0 (kernel infers from the fd type) or one of the CLONE_NEW* constants (acts as a safety check — the call fails if fd doesn't match). The caller must have CAP_SYS_ADMIN in the target namespace's user namespace (CAP_SYS_CHROOT for mount namespaces); user-namespace transitions follow stricter rules (the new userns must be a descendant of the current one, or the caller must hold privilege in the parent). setns() is the syscall behind nsenter(1) and behind every 'docker exec' implementation.
Architecture mapping
| Architecture | Number | ABI | Entry point |
|---|---|---|---|
| x86 (i386) | 346 | i386 | sys_setns |
| x64 (x86_64) | 308 | common | sys_setns |
| ARM64 (aarch64) | 268 | — | sys_setns |
Kernel history
Introduced in Linux 3.0.
3.0
setns() was introduced in 3.0 alongside the broader user/mount/pid namespace tooling that turned earlier kernel work into a coherent toolkit usable from userspace (nsenter, ip netns, container runtimes).
5.8
setns() was extended to accept a pidfd (from pidfd_open() or clone(CLONE_PIDFD)) and a bitmask of CLONE_NEW* flags, so a caller can atomically enter multiple namespaces of a target process without opening individual /proc/<pid>/ns/* files. Required for race-free 'enter every namespace of this process' patterns used by modern container tooling.
seccomp & containers
Docker default profile
Blocked
Podman default profile
Blocked
setns() is BLOCKED by default in Docker and Podman, with good reason: allowing it lets a workload jump into namespaces it shouldn't see, including the host namespaces if any are reachable (e.g. through a misconfigured /proc bind-mount). Enable it only for container-management workloads (the docker engine itself, kubelet) — never for application workloads.
libseccomp
// setns() is NOT on the Docker default allow-list.
seccomp_rule_add(ctx, SCMP_ACT_ERRNO(EPERM), SCMP_SYS(setns), 0);strace example
$ strace -e setns nsenter -t 1 -m /bin/ls /proc 2>&1 | head -3
setns(3, CLONE_NEWNS) = 0setns() with a /proc/<pid>/ns/<type> fd opened just before is the canonical trace pattern. -y resolves the fd to the namespace path, making the trace self-explanatory. nsenter's source is straightforward to read alongside the strace output if you want to understand the full setns sequence.
Security & observability
setns() to /proc/1/ns/mnt is the canonical container-escape primitive — if a workload can reach a file descriptor for the host's PID-1 mount namespace, calling setns() puts it in the host's mount namespace, where it can see and modify any host file. Most escape chains route through this. Mitigations: don't bind-mount /proc into containers, drop CAP_SYS_ADMIN, deny setns() in seccomp (the default). eBPF tracepoint sys_enter_setns is a high-precision signal — any call from a non-init container PID is alert-worthy. From the inside, comparing /proc/self/ns/<type> readlinks against the expected container namespace inodes detects post-hoc escape.
Errors
- EBADF
- fd is not a valid descriptor or does not refer to a namespace.
- EINVAL
- nstype doesn't match the fd's actual namespace type, or the namespace type is not supported by the running kernel.
- ENOMEM
- Insufficient kernel memory.
- EPERM
- Caller lacks CAP_SYS_ADMIN in the target namespace's user namespace, or the requested userns transition violates the parent-descendant rule.