Stage 3 · Build
Namespaces, cgroups & Security
Linux Capabilities
Bounding, permitted, effective, inheritable, and ambient sets with capsh and getpcaps.
Capabilities Overview
Linux capabilities split the power of root into distinct units. Instead of the all-or-nothing root/non-root model, capabilities let you grant specific privileges to processes. This enables fine-grained access control.
# Check capabilities of current shell
capsh --print
# Current: = cap_net_bind_service,cap_sys_admin+ep
# Bounding set = cap_net_bind_service,cap_sys_admin
# Get capabilities of a process
getpcaps $$
# 12345: = cap_net_bind_service,cap_sys_admin+ep
# Check capabilities of a binary
getcap /usr/bin/ping
# /usr/bin/ping = cap_net_admin,cap_net_raw+ep
# Compare with root
sudo getpcaps 1
# 1: = cap_chown,cap_dac_override,cap_fsetid,cap_fowner,
# cap_mknod,cap_net_raw,cap_setgid,cap_setuid,
# cap_setfcap,cap_sepcap+epThe +ep suffix means effective and permitted. cap_net_raw allows ping to use raw sockets without full root privileges.
Capability Sets
| Set | Description |
|---|---|
| Permitted | Capabilities the process can use (restricted by bounding set) |
| Effective | Capabilities currently active for the process |
| Inheritable | Capabilities preserved across execve() |
| Bounding | Maximum capabilities available to the process |
| Ambient | Capabilities inherited by non-privileged executables |
# Permitted set: what the process CAN use
cat /proc/self/status | grep Cap
# CapPrm: 00000000a80425fb
# CapEff: 00000000a80425fb
# CapBnd: 00000000a80425fb
# CapAmb: 0000000000000000
# Decode capabilities
capsh --decode=00000000a80425fb
# 0x00000000a80425fb=cap_chown,cap_dac_override,cap_fsetid,
# cap_fowner,cap_mknod,cap_net_raw,cap_setgid,cap_setuid,
# cap_setfcap,cap_sepcap,cap_net_bind_service,cap_sys_admin
# Effective set: what the process IS using
# If a capability is in permitted but not effective, it's disabledA capability must be in both permitted and effective sets to be active. The bounding set limits what a process can gain through setuid or inheritance.
Key Capabilities
# cap_net_raw — Raw sockets (ping, tcpdump)
# cap_net_bind_service — Bind to ports < 1024
# cap_sys_admin — Most administrative operations
# cap_sys_PTRACE — Trace processes (strace, gdb)
# cap_sys_MODULE — Load kernel modules
# cap_net_ADMIN — Network configuration
# cap_sys_RAW_IO — Direct I/O access
# cap_sys_TIME — Set system clock
# cap_audit_WRITE — Write to audit log
# cap_setuid/cap_setgid — Change UID/GID
# Dangerous capabilities:
# cap_sys_admin — Over 100 different operations
# cap_sys_MODULE — Load arbitrary kernel code
# cap_dac_override — Bypass file permission checkscap_sys_admin is the most powerful capability, covering over 100 operations. Avoid granting it — split into more specific capabilities instead.
Managing Capabilities
# Grant capability to a binary
sudo setcap cap_net_bind_service+ep /usr/bin/myapp
# Remove all capabilities
sudo setcap -r /usr/bin/myapp
# View capabilities
getcap /usr/bin/myapp
# /usr/bin/myapp = cap_net_bind_service+ep
# Use capsh to drop capabilities
capsh --caps="cap_net_bind_service+ep" --keep=1 --uid=$(id -u) -- -c "whoami"
# Run with specific capabilities
capsh --addamb=cap_net_bind_service -- -c "./myapp"Setting capabilities on binaries is more secure than using setuid root. The binary gets only the specific capabilities it needs.
Container Capabilities
# Default Docker capabilities
docker run --rm alpine capsh --print
# Current: = cap_chown,cap_dac_override,cap_fsetid,
# cap_fowner,cap_mknod,cap_net_raw,cap_setgid,
# cap_setuid,cap_setfcap+ep
# Add a capability
docker run --rm --cap-add=NET_ADMIN alpine ip link add veth0 type veth
# Drop ALL capabilities
docker run --rm --cap-drop=ALL alpine capsh --print
# Current: =
# Drop all, add specific
docker run --rm --cap-drop=ALL --cap-add=NET_RAW alpine ping localhost
# Privileged container (all capabilities)
docker run --rm --privileged alpine capsh --print
# Bounding set = full capability setDocker drops most capabilities by default. Only add capabilities that the container actually needs. Never use --privileged in production.
Capability Hardening
# Restrict capability bounding set via systemd
# /etc/systemd/system/myservice.service
[Service]
CapabilityBoundingSet=CAP_NET_BIND_SERVICE
AmbientCapabilities=CAP_NET_BIND_SERVICE
NoNewPrivileges=yes
# Check systemd service capabilities
systemctl show myservice | grep Capability
# CapabilityBoundingSet=cap_net_bind_service
# Verify with capsh
capsh --print | grep "Bounding"CapabilityBoundingSet limits the maximum capabilities a service can have. AmbientCapabilities grants capabilities to the process and its children.
Replace setuid root programs with capability-enhanced binaries. This follows the principle of least privilege and reduces the attack surface.
cap_sys_admin grants access to over 100 kernel operations. Granting it to a container is almost equivalent to running as root. Always split it into more specific capabilities.
Mark this lesson complete to store local progress and unlock a cleaner resume path the next time you visit.