Chapter 3 · Authentication & Access·Intermediate·~16 min

OS Access Control

Linux capabilities split root into named powers; MAC systems (SELinux, AppArmor) constrain processes by policy; namespaces and seccomp build containers.

You will learn

  • What POSIX capabilities replaced about the all-or-nothing root model
  • How SELinux types and contexts differ from AppArmor profiles
  • The seven Linux namespaces and what each isolates
  • What seccomp-bpf restricts and why every modern container runtime uses it

POSIX capabilities

Traditional Unix has one privileged user (root, UID 0) who can do anything. Linux capabilities (since 2.2) split root's powers into ~40 named bits. A few common ones:

  • CAP_NET_BIND_SERVICE: bind to ports below 1024.
  • CAP_NET_RAW: open raw sockets (ping, packet capture).
  • CAP_SYS_ADMIN: the catch-all "still very privileged" bit (mount, set hostname, etc.).
  • CAP_DAC_OVERRIDE: bypass file permission checks.

You can grant a binary one capability without making it setuid root. setcap cap_net_bind_service=+ep /usr/sbin/myserver lets it bind port 80 with no other root powers. Containers strip most caps from PID 1 by default.

SELinux vs AppArmor

Both are Mandatory Access Control (MAC) systems, but they differ in granularity:

  • SELinux (Red Hat, Fedora, Android): type-based. Every process and every file gets a security context like system_u:object_r:httpd_sys_content_t:s0. Policy rules say which types can perform which actions on which other types. Powerful, verbose, hard to debug. Used in security-conscious distros and Android.
  • AppArmor (Ubuntu, Debian, SUSE): path-based profiles. A profile lists which paths a binary can read/write/exec. Simpler to write and reason about. Profiles in /etc/apparmor.d/.

Both run in enforcing or permissive mode. Permissive logs would-be denials without blocking, useful for tuning before enforcement.

The seven Linux namespaces

Namespaces give processes their own view of system resources. The set as of recent kernels:

  • mnt: mount points. Each namespace sees its own filesystem layout.
  • pid: process IDs. The container's PID 1 is its init; outside it has a different PID.
  • net: network interfaces, routing tables, sockets. Each namespace has its own loopback.
  • uts: hostname and domain name.
  • ipc: System V IPC and POSIX message queues.
  • user: UID and GID mappings. The container's root maps to a non-root UID on the host.
  • cgroup: cgroup root view.

The newer time namespace (5.6+) virtualizes the system clock for things like sleeping containers. A "container" is typically a process group joined into a new instance of each of these.

seccomp-bpf

seccomp ("secure computing") restricts which syscalls a process may make. The original "strict" mode allows only read, write, exit, and sigreturn. The much more useful seccomp-bpf mode runs a Berkeley Packet Filter on every syscall and decides per call.

Docker's default seccomp profile blocks ~50 syscalls including kexec_load, open_by_handle_at, userfaultfd (used in many container escapes), and perf_event_open. Custom profiles can be tighter, allowing only the syscalls the workload genuinely needs.

The pattern: container runtimes layer namespaces (for resource isolation) + capability drops (for privilege reduction) + seccomp (for syscall reduction) + a MAC system (SELinux/AppArmor for policy). Each layer is independently bypassable; together they raise the bar substantially.

Container escapes happen here

Real CVE classes:

  • Kernel vulnerabilities the container shares with the host (CVE-2022-0185, Dirty Pipe).
  • runc / containerd bugs in the runtime that allow escaping from the namespace.
  • Misconfigured capability drops that leave dangerous capabilities, or running with --privileged which disables most of the above.
  • Mount escapes where the container can mount the host filesystem (often via CAP_SYS_ADMIN).

Defense: run containers as non-root user, drop all capabilities and add back only what is needed, set readOnlyRootFilesystem: true, disable privilege escalation, run a seccomp profile, and patch the host kernel promptly.