guest@6admin.io:~$

Containers, micro-VMs et Firecracker : pourquoi l'isolation n'est pas ce que vous croyez

Un container Docker n’est pas une VM. C’est un process avec des namespaces. Le kernel est partagé: le même Linux, le même syscall table, le même code kernel, la même pile réseau. Une faille dans le kernel ouvre TOUS les containers sur la machine, pas un.

C’est une distinction que les articles de ce blog documentent depuis 2006: le chroot qui dépasse par un symlink, le raw socket qui voit tout le réseau, le socket qui parle TCP parce que le kernel fait le transport. Chacune de ces techniques fonctionne parce que l’isolation container est un partage, pas une frontière matérielle.

La chaîne d’isolation, du plus faible au plus fort

Process        → isolation nulle (un process peut tuer les autres)
Chroot         → isolation du filesystem par chemin (symlink escape)
Namespaces     → isolation kernel par type (pid, net, mnt, user)
+ seccomp      → filtrage des syscalls
+ AppArmor/SELinux → contrôle d'accès obligatoire
+ cgroups      → plafonnement des ressources
──────────────────────────────────────────────────────────────
= Container (Docker, Podman): tout ce qui précède, même kernel
──────────────────────────────────────────────────────────────
Micro-VM (Firecracker)  → isolation hardware (Intel VT-x, AMD-V)
VM (KVM, Hyper-V)       → isolation hardware + hyperviseur
Machine physique        → isolation matérielle

Le container empile des mécanismes kernel: namespaces pour l’isolation des vues, seccomp pour filtrer les syscalls, AppArmor/SELinux pour le contrôle d’accès obligatoire, cgroups pour les ressources. Chaque couche est un filtre kernel. Le kernel est l’arbitre ET le jouet: une faille kernel contourne toutes les couches simultanément.

La faille kernel: le talon d’Achille du container

Dirty COW (CVE-2016-5195), Dirty Pipe (CVE-2022-0847), CVE-2022-0185 (container escape via legacy_parse_param), CVE-2024-1086 (nf_tables use-after-free): chaque faille kernel est un container escape potentiel. Elles fonctionnent PARCE QUE le kernel est partagé: le container exécute des syscalls dans le même kernel que l’hôte et une corruption de mémoire kernel depuis le container contamine l’hôte.

Les mitigations existent (seccomp pour réduire la surface de syscalls, AppArmor pour le contrôle d’accès, user namespaces pour le mapping des UID), mais elles sont kernel-based: une faille kernel les contourne toutes. C’est la différence fondamentale entre une isolation logicielle (kernel) et une isolation matérielle (VT-x, AMD-V).

La micro-VM: VM-level isolation à container speed

Firecracker (AWS) crée des micro-VMs qui bootent en ~125 ms avec ~5 Mo d’overhead mémoire. Chaque micro-VM a son PROPRE kernel, isolé par KVM (Intel VT-x / AMD-V), sans console, sans SSH, sans systemd: juste le binaire de l’application.

La différence avec un container:

  • Kernel dédié : chaque micro-VM a son propre kernel, isolé par le hardware. Une faille kernel dans une micro-VM ne contamine PAS l’hôte ni les autres micro-VMs.
  • Surface minimale : pas de shell, pas de SSH, pas de démon réseau. Le process, le kernel minimal et rien d’autre.
  • Boot rapide : 125 ms, contre plusieurs secondes pour une VM complète ou plusieurs minutes pour un provisionnement bare-metal.

Les unikernels (MirageOS, Unikraft, OSv) vont plus loin: un kernel single-purpose compilé avec l’application, sans userspace, sans shell, sans syscall table générique. La surface d’attaque se réduit au minimum vital.

Ce que ça change

Le container reste le bon outil pour l’orchestration (Kubernetes, les volumes, le réseau). La micro-VM est le bon outil pour l’isolation (multi-tenant, serverless, le code non approuvé). Les deux ne s’excluent pas: Kata Containers fait tourner des containers dans des micro-VMs et Firecracker est le VMM de Fargate.

Mais si votre modèle de menace inclut des failles kernel, le container seul ne suffit pas. La faille nf_tables qui permet un escape de chroot par symlink ou le Dirty Pipe qui écrit dans des fichiers read-only, fonctionnent dans les containers ET dans les chroots. L’isolation matérielle (VT-x) ne peut pas être contournée par un bug kernel guest: l’hyperviseur est une frontière différente, dans un anneau d’exécution différent.