Skip to content
Operating Systems

Virtualisation, containers and security

Hardware protection, the Popek and Goldberg theorem, type 1 and 2 hypervisors, the cost of nested page tables proved, namespaces and cgroups, security principles.

A modern data centre does not run one operating system per machine: it runs dozens, each in a virtual machine, or thousands of applications isolated in containers. Virtualisation made the cloud possible, and it rests on the same protection mechanisms that separate processes. In this lesson we look at hardware protection, the Popek and Goldberg theorem on virtualisability with its justification, the hypervisor and hardware support with the calculation of the cost of two-level address translation, containers and some security principles.

Protection

Isolation between processes rests on three hardware mechanisms, controlled by the kernel:

  • privileged mode (lesson on processes): only the kernel executes the instructions that configure the system;
  • address translation: each process sees only the pages its table maps, with read, write and execute permissions per page (lesson on memory);
  • timer interrupts: the kernel regains control periodically, even from a process that never calls the system.

When a machine can be virtualised

A hypervisor (or virtual machine monitor) runs several guest operating systems, making each believe it has the machine to itself. The natural method is trap-and-emulate: the guest kernel runs in user mode; when it executes a privileged instruction, the processor raises an exception, the hypervisor intercepts it and emulates the effect on the virtual machine.

Popek and Goldberg (1974) distinguished sensitive instructions, which read or modify the machine’s configuration state (mode, page tables, interrupts), and privileged ones, which cause an exception in user mode.

Theorem (Popek and Goldberg). An efficient hypervisor can be built with the trap-and-emulate method if the set of sensitive instructions is contained in the set of privileged instructions.

Justification. If every sensitive instruction is privileged, every attempt by the guest to touch the configuration causes an exception and reaches the hypervisor, which emulates it on the virtual state: the hypervisor keeps control. All the other instructions do not touch the configuration and can run directly on the processor, at full speed. If instead a sensitive instruction were not privileged, the guest in user mode would execute it without an exception, with an effect different from the one expected in kernel mode, and the hypervisor would not notice. ∎

The original x86 architecture violated the condition: some instructions, such as the one restoring the processor flags, behaved differently in user mode without raising exceptions. The first solutions were binary translation (VMware rewrote the guest kernel’s code on the fly) and paravirtualisation (Xen modified the guest kernel so that it called the hypervisor). Since 2005-2006 processors have dedicated extensions (Intel VT-x, AMD-V) with a new mode for the hypervisor, which make the machine virtualisable according to the theorem.

Hypervisors and memory

A type 1 hypervisor runs directly on the hardware (ESXi, Xen, Hyper-V, KVM built into the Linux kernel); a type 2 one runs as an application on a host operating system (VirtualBox).

Virtual machines and containers
On the left: on the hardware HW runs the hypervisor HV, which hosts three virtual machines, each with its own operating system OS and its own applications A. On the right: on the hardware runs a single operating system, with a container engine CE isolating three applications, which share the same kernel.

Memory requires a two-level translation: the guest translates virtual addresses into “guest physical” addresses, and the hypervisor translates these into real physical addresses. Modern processors do both in hardware with nested page tables (EPT, NPT).

Theorem. With n-level tables in the guest and m-level tables in the hypervisor, a TLB miss can require up to (n + 1)(m + 1) - 1 memory accesses.

Proof. The guest translation reads n table entries, and then there is the final data address: n + 1 guest physical addresses in all, each to be translated with the hypervisor’s table, which requires m reads. Add the n reads of the guest entries themselves (the final data access is not counted, since it is there even without virtualisation). Total m(n + 1) + n = (n + 1)(m + 1) - 1. ∎

Example. With four levels in both, 5\cdot 5 - 1 = 24 accesses instead of 4: this is why the TLB and page-table entry caches are even more important in virtual machines, and why huge pages pay off.

Containers

A container does not virtualise the hardware but the operating system: applications share a single kernel, which gives each group of processes a separate view of resources with namespaces (processes, network, file system, users) and limits their consumption with control groups (cgroups: CPU, memory, input and output). A container starts in fractions of a second and occupies only the application’s memory; an image (Docker, Podman) packages the application with all its libraries and runs the same everywhere. The price is weaker isolation: a flaw in the shared kernel exposes all containers, whereas a virtual machine has its own kernel. This is why in public cloud services the containers of different customers often run inside lightweight virtual machines.

Security principles

  • Least privilege: every program has only the permissions it needs; a network service does not run as administrator.
  • Defence in depth: several independent barriers, because each can have flaws.
  • Protection against exploitation of memory errors: non-executable data pages (NX bit), address space layout randomisation (ASLR), which makes addresses unpredictable to anyone trying to hijack the program, canary values on the stack.
  • Updates: most successful attacks exploit vulnerabilities that are already known and fixed, but not installed.
Subscribe
Notify of
guest
0 Comments
Oldest
Newest Most Voted
0
Would love your thoughts, please comment.x
()
x