Stage 3 · Build
Namespaces, cgroups & Security
PID, Mount & User Namespaces
unshare, setns, bind mounts, UID maps, and rootless isolation mechanics.
Namespace Overview
Namespaces are the kernel primitives that isolate system resources. Each namespace type wraps a global resource so that processes in different namespaces see different instances. Linux has 8 namespace types.
| Namespace | Isolates | Key Resource |
|---|---|---|
| pid | Process IDs | PID number space |
| net | Network stack | Interfaces, routing tables, firewall |
| mnt | Mount points | Filesystem hierarchy |
| user | User/Group IDs | UID/GID mappings |
| uts | Hostname/domain | Nodename and domainname |
| ipc | IPC resources | Shared memory, semaphores, message queues |
| cgroup | Cgroup root | Cgroup hierarchy view |
| time | System clocks | CLOCK_MONOTONIC, CLOCK_BOOTTIME |
# View namespace for current process
ls -la /proc/self/ns/
# lrwxrwxrwx 1 root root 0 ... cgroup -> 'cgroup:[4026531835]'
# lrwxrwxrwx 1 root root 0 ... ipc -> 'ipc:[4026531839]'
# lrwxrwxrwx 1 root root 0 ... mnt -> 'mnt:[4026531840]'
# lrwxrwxrwx 1 root root 0 ... net -> 'net:[4026531969]'
# lrwxrwxrwx 1 root root 0 ... pid -> 'pid:[4026531836]'
# lrwxrwxrwx 1 root root 0 ... user -> 'user:[4026531837]'
# lrwxrwxrwx 1 root root 0 ... uts -> 'uts:[4026531838]'
# Compare with another process
readlink /proc/1/ns/pid
# pid:[4026531836] (same namespace)
Each namespace has a unique inode number. Processes in the same namespace share the same inode value.
PID Namespaces Deep Dive
# Create a nested PID namespace
sudo unshare --pid --fork --mount-proc bash
# Inside: PID 1 is your shell
echo $$ # 1
ps aux # Only shows this namespace
# Check namespace hierarchy from host
readlink /proc/<container_pid>/ns/pid
# Kill PID 1 in child namespace
kill -9 1 # Kills only the child namespace
# Parent namespace is unaffected
# Nested namespaces: child sees parent, parent cannot see child
# PID 1 in child = PID 12345 in parentPID namespaces can be nested. PID 1 in the child namespace has a different PID in the parent. Killing PID 1 in a namespace terminates all processes in that namespace.
Mount Namespaces
# Create a new mount namespace
sudo unshare --mount bash
# Mount something new (not visible outside)
mount -t tmpfs tmpfs /mnt
ls /mnt/ # Empty
ls / # Has tmpfs mounted
# Bind mount from parent namespace
mount --bind /proc /mnt/proc
# Mount namespace + pivot_root for containers
# 1. Create new mount namespace
# 2. Mount new root filesystem
# 3. pivot_root to new root
# 4. Unmount old rootMount namespaces give each container its own filesystem view. Changes to mounts are invisible to other namespaces.
User Namespaces
# Create a new user namespace (as unprivileged user)
unshare --user --map-root-user bash
# Inside: you are root (UID 0)
whoami # root
id # uid=0(root) gid=0(root)
# Check UID mapping
cat /proc/self/uid_map
# 0 1000 1
# This means: UID 0 in namespace = UID 1000 outside, count=1
# From outside, check the mapping
readlink /proc/<ns_pid>/ns/user
cat /proc/<ns_pid>/uid_mapUser namespaces let unprivileged users create isolated UID spaces. The user is root inside the namespace but remains unprivileged outside.
UID Mapping
# Automatic mapping with newuidmap/newgidmap
# /etc/subuid
# username:100000:65536
# /etc/subgid
# username:100000:65536
# This means:
# username can map UIDs 100000-165535
# username can map GIDs 100000-165536
# View mappings
cat /proc/<pid>/uid_map
# 0 1000 1
# 1 100000 65535
cat /proc/<pid>/gid_map
# 0 1000 1
# 1 100000 65535
# Manual mapping
echo "0 $(id -u) 1" > /proc/<pid>/uid_map
echo "0 $(id -g) 1" > /proc/<pid>/gid_mapUID mappings translate between namespace UIDs and host UIDs. The first column is the namespace UID, the second is the host UID, and the third is the count.
Rootless Containers
# Rootless Docker/Podman setup
# 1. Create user namespace
# 2. Map host UIDs to namespace UIDs
# 3. Use slirp4netns for networking
# 4. Use fuse-overlayfs for overlayfs
# Check rootless support
cat /proc/sys/kernel/unprivileged_userns_clone
# 1 (enabled)
# Set up subuid/subgid ranges
sudo usermod -v 100000-165535 $(whoami)
sudo usermod -w 100000-165535 $(whoami)
# Run container rootlessly
podman run --rm alpine echo "Hello from rootless container"
# Check namespace isolation
podman run --rm alpine cat /proc/1/uid_map
# 0 100000 65536Rootless containers run entirely as a regular user. User namespaces provide root-like capabilities without actual root privileges.
unshare lets you create namespaces without a container runtime. Use it to test namespace isolation before implementing in production.
User namespaces allow unprivileged users to create namespaces with root-like capabilities. Some distributions disable this by default. Ensure proper UID mapping to prevent privilege escalation.
Mark this lesson complete to store local progress and unlock a cleaner resume path the next time you visit.