← All chapters

Chapter 1

Two models: shared kernel vs. own kernel

Every isolation technology is one of two things.

Every tool in this field, every container runtime, every process sandbox, every virtual machine, answers one question before any other: when the code inside the box runs, whose kernel does it talk to? There are only two answers. Either the box shares the host kernel, or it brings its own.

Shared kernel

In the shared-kernel model, the process inside the box makes its straight into your kernel, the same kernel your shell and your browser are using right now. Nothing is emulated; the isolation is just the kernel agreeing to show that process a narrower view of itself. A Docker container is this: an ordinary process fenced off with Linux Linux namespaces and other kernel isolation features. So is a process sandbox like bubblewrap or macOS's Seatbelt (macOS App Sandbox), and so is gVisor (runsc) (runsc), except gVisor adds another critical layer of protection: it uses seccomp-BPF to filter which syscalls reach the host kernel at all.

This model is cheap and fast: a container starts in milliseconds and adds almost no overhead. And it is one kernel bug away from an escape. Any code that can trick the shared kernel into running as root is now root on the host, because there is nothing underneath the kernel to catch it.

Own kernel

In the own-kernel model, a , KVM on Linux, Hypervisor.framework on macOS, hands the box its own kernel, running on virtual hardware behind a boundary the CPU itself enforces. That is a virtual machine; a microVM is the same idea stripped down to boot in a fraction of a second. The code inside makes its syscalls into its guest kernel, not yours. To reach the host it must first break out of the virtual hardware, a far smaller, far better-audited target than the entire Linux syscall surface.

Shared kernel

proc
proc
proc
host kernel

one kernel bug escapes every box

The dividing line is the kernel.

Own kernel

VM
own guest kernel
VM
own guest kernel
hypervisor
host kernel

a hardware boundary per box

Left: containers and process sandboxes stack straight on the host kernel. Right: each VM carries its own guest kernel behind a hardware boundary enforced by the hypervisor.

The dividing line is the kernel.

Everything on the shared side of that line runs on the host kernel, so a single kernel privilege-escalation bug defeats all of it at once, container, process sandbox, and userspace-kernel alike. Everything on the own side has its own kernel behind a hardware boundary, and that same bug stays contained. This is the fault line the rest of the tutorial is organized around; when a tool claims to isolate something, the first question is always which side of the line it is on.

Two models, two jobs

Shared-kernel isolation is the right fit for code you trust, your own project, your own dependencies, an agent you are supervising. There you want reproducibility and resource limits; paying for a full VM buys friction with little benefit. The mistake in the other direction is worse: running genuinely hostile code in a shared-kernel container introduces more risk than a microVM or a full VM. And the symmetry holds: own-kernel isolation buys a smaller attack surface, never the word "secure." Match the tier to the threat.

Before we can talk about escaping the shared-kernel box, we need to know what it is actually made of. In Anatomy of a container we open one up.

Reference these in the dictionary