◇ OpenCyber Academy
Engineering · Chapter 12 · English

Chapter 12 — Operating systems

Open, free learning for anyone who wants to protect people and technology. No account is required to read this text or its worked answers.

Chapter 12 — Operating systems

Lesson map

Lesson 12 published. Map, example, EX034.

flowchart TD
  N0["Learning outcomes"]
  N1["12.1 Namespaces"]
  N2["12.2 Capabilities"]
  N3["Lab — Lab — container capabilities"]
  N4["12.3 Lab result"]
  N5["12.4 Running as non-root"]
  N6["12.5 Seccomp"]
  N7["12.6 Checking in practice"]
  N0 --> N1 --> N2 --> N3 --> N4 --> N5 --> N6 --> N7
  N7 --> EX["Worked example"]
  EX --> Q["Exercise EX034"]

Logical drawing

flowchart LR
  N0["Learning outcomes"]
  N1["12.1 Namespaces"]
  N2["12.2 Capabilities"]
  N3["Lab — Lab — container capabilities"]
  N4["12.3 Lab result"]
  N5["12.4 Running as non-root"]
  N6["12.5 Seccomp"]
  N7["12.6 Checking in practice"]
  N0 --> N1 --> N2 --> N3 --> N4 --> N5 --> N6 --> N7 --> Q["EX034"]
[Learning outcomes]
    |
    v
[12.1 Namespaces]
    |
    v
[12.2 Capabilities]
    |
    v
[Lab — Lab — container capabilities]
    |
    v
[12.3 Lab result]
    |
    v
[12.4 Running as non-root]
    |
    v
[12.5 Seccomp]
    |
    v
[12.6 Checking in practice]
    |
    v
[Worked example] --> [Exercise EX034]

Learning outcomes

You will (1) explain how containers use Linux kernel features; (2) describe capabilities, namespaces and control groups; (3) apply least privilege to containers; (4) check capability sets.

12.1 Namespaces

Containers are processes isolated by Linux namespaces: each sees its own process list, network interfaces, mount points and hostname. Isolation comes from the shared kernel, so kernel settings matter.

A container's process list shows only its own processes because of the PID namespace; its network namespace gives it a separate interface and routing table. These are views provided by the kernel, not separate machines. A flaw in the kernel, or a setting that grants access to the host's namespaces, breaks the illusion, which is why host-level settings such as hostNetwork are checked closely.

12.2 Capabilities

Linux splits root privileges into capabilities such as NET_BIND_SERVICE (bind low ports), CHOWN (change file owners) and SYS_ADMIN (a very broad set of administrative powers). A container should drop all and add only what it needs; NIST SP 800-190 recommends limiting container privileges.

Running as root inside a container used to mean holding every capability, including powerful ones like loading kernel modules. Splitting them lets a web server bind to port 443 without also being able to reconfigure the network. Dropping all and adding back only what is needed makes each container's power explicit and reviewable.

Lab — Lab — container capabilities

"""Compare synthetic container capability sets with a drop-all-add-needed baseline (stdlib only)."""
needed = {"meter-ingest": {"NET_BIND_SERVICE"}, "report-api": set(), "node-agent": {"SYS_PTRACE"}}
actual = {"meter-ingest": {"NET_BIND_SERVICE", "CHOWN", "SETUID"}, "report-api": set(),
          "node-agent": {"SYS_ADMIN", "SYS_PTRACE", "NET_ADMIN"}}
for c in actual:
    extra = sorted(actual[c] - needed[c])
    print(f"{c:13} extra capabilities: {', '.join(extra) or 'none'}")

Run with python3 lab_caps.py. Verified output:

meter-ingest  extra capabilities: CHOWN, SETUID
report-api    extra capabilities: none
node-agent    extra capabilities: NET_ADMIN, SYS_ADMIN

12.3 Lab result

meter-ingest has two extra capabilities, CHOWN and SETUID, beyond the NET_BIND_SERVICE it needs. report-api has none extra. node-agent has NET_ADMIN and SYS_ADMIN beyond the SYS_PTRACE it needs. SYS_ADMIN is the most serious because it grants broad control close to full root.

CHOWN and SETUID on meter-ingest probably serve a start-up step that sets file ownership; removing them means moving that work into the image build, which needs testing. node-agent's case needs more care, since it monitors the node and genuinely needs some power, but SYS_ADMIN is far more than tracing requires. Elena raises it as the top finding with a suggested reduced set.

12.4 Running as non-root

Containers should run as a non-root user with a read-only root filesystem where possible. The Restricted profile of the Pod Security Standards requires runAsNonRoot and disallows privilege escalation.

A process running as root inside a container is one kernel flaw away from root on the host. Running as an ordinary user removes that step. A read-only root filesystem stops an attacker from writing tools or changing binaries inside the container; writable space is given only where needed, through specific volumes.

12.5 Seccomp

Seccomp profiles limit which system calls a container may make. The runtime default profile blocks many rarely needed calls and is required by the Restricted profile.

Many system calls exist for rare administrative tasks that ordinary applications never use. Each one is a possible path into the kernel if it contains a bug. Blocking unused calls shrinks that attack surface. The runtime default suits most applications; where a workload needs an unusual call, a custom profile adds it explicitly. Profiles are kept in version control.

12.6 Checking in practice

Capability sets come from pod specifications; Elena's checker compares them with a documented "needed" list per workload.

The 'needed' list is written by each workload's owner with a short reason for every capability. Elena's checker then reports any capability in the spec that is not on the list, and any listed capability that the spec no longer uses. Both kinds of difference prompt a review, keeping the list and the deployment in step. The list is reviewed when a workload's owner changes, so knowledge of why each capability exists is not lost.

Worked example

The node-agent's owners explain that SYS_ADMIN was copied from an old example. Testing on the test cluster shows the agent works with only SYS_PTRACE. NET_ADMIN is removed too, and meter-ingest drops CHOWN and SETUID after its image is rebuilt to set file ownership at build time.

Synthetic case. Workloads and capabilities are synthetic.

Errors and limits

Removing capabilities can break software in rare code paths; test thoroughly.

Exercises

Synthesis

Containers should drop capabilities and run as non-root.

Continue studying — chapter 12 of 50

← Chapter 11 (draft) · Course chapter index · Chapter 13 (draft) →