1 Punkte von GN⁺ 2 시간 전 | 1 Kommentare | Auf WhatsApp teilen
  • CVE-2026-31431 Copy Fail ermöglicht es lokalen nicht privilegierten Benutzern, eine root-Shell zu erhalten, und erlaubt auch innerhalb von Podman-Rootless-Containern eine Privilegieneskalation zu internem root
  • Podman-Rootless-Container kombinieren User Namespaces, UID-Isolierung und Linux Capabilities, um internes root im Container auf einen nicht privilegierten Benutzer auf dem Host abzubilden und Host-Berechtigungen zu begrenzen
  • In Tests konnte der Benutzer foo in einem rootless non-root Container nach Ausführung von Copy Fail zwar zu internem root im Container werden, die Rechte blieben jedoch auf den Umfang des nicht privilegierten Host-Benutzers bar beschränkt, und Host-Dateien im Besitz von root konnten nicht gelesen werden
  • Wenn --security-opt=no-new-privileges oder --cap-drop=all angewendet wird, bleibt die Shell auch nach Ausführung von Copy Fail beim Benutzer foo und mit Capabilities none, wodurch eine unmittelbare Erlangung einer root-Shell und eine Capability-Eskalation verhindert werden können
  • Die Auswirkungen von Copy Fail können über den Lebenszyklus des Containers hinaus bestehen bleiben, daher sind Kernel-Patches und ein Neustart erforderlich; außerdem sollte Defense in Depth mit einem schreibgeschützten Root-Dateisystem, cgroups-Ressourcenlimits, schlanken Runtime-Images und Firewalls gemeinsam eingesetzt werden

Reichweite der Exponierung von Copy Fail und Podman-Rootless-Containern

  • CVE-2026-31431 wurde am 29. April auf copy.fail veröffentlicht; durch Ausführung des veröffentlichten Python-Skripts kann ein lokaler nicht privilegierter Benutzer eine root-Shell erhalten
  • Copy Fail kann auch innerhalb von Linux-Containern ausgenutzt werden, und auch in Podman-Rootless-Containern ist der Erhalt einer internen root-Shell im Container möglich
  • In den Tests war Container-root auf Host-Ebene auf den Berechtigungsumfang des nicht privilegierten Benutzers bar begrenzt, der den Container gestartet hatte
  • Die Rootless-Implementierung von Podman kombiniert User Namespaces, UID-Isolierung und Linux Capabilities, um die Host-Berechtigungen von Container-Prozessen zu begrenzen
  • Copy Fail zeigt, dass auch Rootless-Container nicht immun gegen die Schwachstelle sind, dass sich der Angriffsradius nach einer Kompromittierung mit Podman-Einstellungen jedoch verringern lässt

Funktionsweise von Rootless-Containern

  • Grundbeispiel: Nicht privilegierter Benutzer bar startet einen HTTP-Server

    • Die Beispielumgebung besteht daraus, dass der nicht privilegierte Benutzer bar mit UID 1001 mit Podman ein auf ubuntu:latest basierendes Image baut und python3 -m http.server ausführt
    • Auf dem Host ist mit ps zu sehen, dass der python3-Prozess als Benutzer bar ausgeführt wird
    • Podman verwendet ein Fork/Exec-Modell, daher werden Container-Prozesse zu Nachkommen des Prozesses podman run; durch die übliche UID-Isolierung lassen sich Container-Prozesse von Host-root oder anderen Benutzern trennen
    • In einer typischen Docker-Konfiguration kann auch dann, wenn ein nicht privilegierter Benutzer docker run ausführt, der Docker-Client mit einem Daemon mit Root-Rechten kommunizieren, und da der Daemon letztlich den Container-Prozess erzeugt, kann dieser auf dem Host als root erscheinen
  • Rootless rootful

    • Wenn ein Container-Image keine explizite USER-Anweisung oder kein --user-Flag enthält, wird der Container-Befehl gewöhnlich intern als root ausgeführt
    • In der Ausgabe von podman top wird der HTTP-Server-Prozess auf den Host-Benutzer 1001 abgebildet, intern im Container jedoch als root ausgeführt
    • Diese Konfiguration ist auf dem Host nicht privilegiert, innerhalb des Containers jedoch root und befindet sich somit im Zustand rootless rootful
  • User Namespaces

    • Podman-Rootless-Container verwenden User Namespaces, um UID/GID innerhalb und außerhalb des Containers unterschiedlich abzubilden
    • Im Beispiel wird internes root mit UID 0 im Container auf bar mit der Host-UID 1001 abgebildet
    • Die Einstellung bar:165536:65536 in /etc/subuid legt den UID-Bereich fest, der den Namespace-Prozessen von bar zugewiesen werden kann
    • Im Beispiel können zusätzlich zur UID 1001 von bar UIDs von 165536 bis 231072 den Prozessen von bar zugewiesen werden
    • Wenn sleep als interner Container-Benutzer www-data ausgeführt wird, ist es intern www-data, auf dem Host wird es jedoch als 165568 angezeigt
    • Wenn man mit podman unshare den User Namespace betritt, erscheint das auf dem Host bar:bar gehörende Home-Verzeichnis innerhalb des Namespace als root:root
    • Docker unterstützt ebenfalls User Namespaces, erfordert dafür jedoch eine separate Konfiguration und erlaubt nur einen einzigen User Namespace, während Podman die Rootless-Container jedes UNIX-Benutzers im jeweiligen User Namespace dieses Benutzers ausführt
  • Privilegierte Operationen und Linux Capabilities

    • Podman verwendet Linux Capabilities, um Container-Prozessen fein granulierte Root-Rechte zu gewähren
    • Während des Image-Builds werden Vorgänge wie apt install durch eine Kombination von Capabilities wie chown, dac_override, fowner, setgid, setuid, net_bind_service und sys_chroot möglich
    • Wenn mit podman build --cap-drop=all alle Capabilities entfernt werden, schlägt der Image-Build fehl, weil apt bei setgroups, setegid, seteuid, chown und Ähnlichem scheitert
    • Es ist auch möglich, nur die benötigten Capabilities hinzuzufügen; im Beispiel werden CAP_SETUID,CAP_SETGID,CAP_CHOWN,CAP_DAC_OVERRIDE,CAP_FOWNER hinzugefügt, um die Paketinstallation durchzuführen
    • Der HTTP-Server im Standardlauf wird intern im Container als root ausgeführt und besitzt viele effektive Capabilities wie CHOWN,DAC_OVERRIDE,FOWNER,FSETID,KILL,NET_BIND_SERVICE,SETFCAP,SETGID,SETPCAP,SETUID,SYS_CHROOT
    • Der HTTP-Server benötigt diese Rechte nicht, daher können mit podman run --cap-drop=all alle Capabilities entfernt werden; in podman top werden die effektiven Capabilities dann als none angezeigt
  • Rootless non-root

    • Um den HTTP-Server auch innerhalb des Containers als nicht privilegierten Benutzer auszuführen, kann ein vorhandener Benutzer aus /etc/passwd, etwa www-data, verwendet oder während des Image-Builds ein eigener Benutzer angelegt werden
    • Im Beispiel werden ein Benutzer und eine Gruppe foo mit UID 1002 erstellt, Lesezugriff auf /var/www/html gewährt und anschließend USER foo:foo gesetzt
    • Wenn dieses Image mit --cap-drop=all ausgeführt wird, läuft der Prozess intern im Container als foo, mit Host-UID 166537 und effektiven Capabilities none
    • Container-Prozesse sollten mit den minimal nötigen Rechten ausgeführt werden; wenn foo beispielsweise an den privilegierten Port 80 binden muss, sollte --cap-add=CAP_NET_BIND_SERVICE hinzugefügt werden
    • Die Ausführungsarten von Containern lassen sich in vier Kategorien einteilen
      • Host-Benutzer root + Container-root: root rootful
      • Host-Benutzer root + nicht privilegierter Container-Benutzer: root non-root
      • Nicht privilegierter Host-Benutzer + Container-root: rootless rootful
      • Nicht privilegierter Host-Benutzer + nicht privilegierter Container-Benutzer: rootless non-root
    • Podman macht das Starten von rootless rootful Containern einfach, und wenn sich Container-Prozesse als nicht privilegierte Benutzer ausführen lassen, ist auch eine rootless non-root Konfiguration vergleichsweise leicht umzusetzen

Bind-Mounts und UID-Isolierung

  • Wenn ein Host-Verzeichnis in den Container gemountet wird, hängt der Zugriff auf Dateien, die Host-root, Host-bar oder Namespace-foo gehören, vom UID-Mapping ab.
  • Im Beispiel werden im Verzeichnis /var/lib/bar/test die Datei root.txt im Besitz von Host-root und bar.txt im Besitz von Host-bar erstellt und im Container nach /test mit Lese-/Schreibrechten gemountet.
  • Wird der Container als foo ausgeführt, erscheint die Datei im Besitz von Host-bar im Container als root:root, während die Datei im Besitz von Host-root, da sie nicht in den Namespace gemappt ist, als nobody:nogroup erscheint.
  • foo im Container kann weder bar.txt noch root.txt lesen, und rootless non-root bietet zusätzliche Isolierung gegenüber rootless rootful.
  • foo.txt, das foo im gemounteten Verzeichnis erstellt, erscheint auf dem Host als Datei im Besitz der UID 166537, und der Host-Benutzer bar kann den Inhalt dieser Datei nicht lesen.
  • Wird der Container als internes root ausgeführt, kann Namespace-root die Dateien im Besitz von Host-bar und von foo lesen, aber nicht die Datei root.txt im Besitz von Host-root.
  • Wird bei der Ausführung als internes root zusätzlich --cap-drop=all angewendet, kann auch die Datei von foo nicht gelesen werden, und nur die Datei im Besitz von Host-bar bleibt lesbar.

Copy-Fail-Test

  • Testbedingungen

    • Für den Copy-Fail-Test wurde die Exploit-Version des ursprünglich veröffentlichten Commits 8e918b5 verwendet.
    • Das Beispiel-Container-Image erweitert ein vorhandenes HTTP-Server-Image um curl, damit das Exploit-Skript im Container heruntergeladen werden kann.
    • Das Image wird unter dem Namen copyfail gebaut.
    • Der Test-Kernel ist Debians 6.12.74+deb13+1-amd64; nach Debian-Maßstab gelten neuere Versionen unterhalb von 6.12.85 noch als ungepatchte Kernel, die dafür verwendet werden können.
    • Wenn der unprivilegierte Benutzer foo normalerweise su aufruft, wird das root-Passwort verlangt.
    • In jedem Test lädt der Container-Benutzer das Copy-Fail-Skript nach /tmp herunter, führt es aus und ruft bei erfolgreichem Erlangen einer root-Shell sleep auf.
    • Da Copy Fail über den Container-Lebenszyklus hinaus bestehen bleibt, wird die VM vor jedem Test neu gestartet.
  • Ergebnis bei rootless rootful

    • Wenn der Container mit --user=root gestartet wird, sind die Prozesse im Container bereits root.
    • Wird in diesem Zustand das Copy-Fail-Skript ausgeführt und su aufgerufen, erhält man zwar eine Shell mit uid=0(root), aber da der Benutzer root ohnehin ohne Passwort per su eine weitere root-Shell öffnen kann, bringt Copy Fail praktisch keinen zusätzlichen Effekt.
    • In podman top werden /bin/bash, python3 copy_fail_exp.py, su und sleep jeweils als internes Container-root und als Host-Benutzer 1001 angezeigt.
    • Es bleibt derselbe Capability-Satz erhalten; sichtbar sind CHOWN,DAC_OVERRIDE,FOWNER,FSETID,KILL,NET_BIND_SERVICE,SETFCAP,SETGID,SETPCAP,SETUID,SYS_CHROOT.
    • Internes root kann im gemounteten /test bar.txt und foo.txt lesen, aber nicht root.txt, das Host-root gehört.
  • Ergebnis bei rootless non-root

    • Wird der Container als foo ausgeführt und danach das Copy-Fail-Skript gestartet und su aufgerufen, erfolgt eine Rechteausweitung zu internem Container-root.
    • Das id der resultierenden Shell wird als uid=0(root) gid=1002(foo) groups=1002(foo) angezeigt.
    • In podman top erscheinen das anfängliche /bin/bash, der Prozess zur Ausführung des Exploits und der su-Aufruf mit Host-UID 166537, Container-Benutzer foo und Capabilities none.
    • Nach der Rechteausweitung werden [sh] und sleep als Host-Benutzer 1001 und Container-Benutzer root angezeigt und erhalten denselben Capability-Satz wie bei rootless rootful.
    • Auch das eskalierte Container-root kann root.txt im Besitz von Host-root nicht lesen.
    • In diesem Zustand ist der Container zwar kompromittiert, aber der Angriffsbereich bleibt auf den Container und das beschränkt, was der unprivilegierte Host-Benutzer bar tun kann.
  • Ergebnis bei Anwendung von no-new-privileges

    • Mit --security-opt=no-new-privileges kann Podman verhindern, dass Container-Prozesse mehr Rechte erhalten als beim Start.
    • Wird diese Option auf einen rootless non-root-Container angewendet und Copy Fail ausgeführt, öffnet sich zwar eine Shell, sie bleibt jedoch im Zustand uid=1002(foo).
    • Auch in podman top bleiben alle Prozesse bei Host-UID 166537, Container-Benutzer foo und Capabilities none.
    • Auch im gemounteten /test kann foo nur die eigene Datei lesen und weder bar.txt noch root.txt.
    • Der Container ist kompromittiert, bleibt aber auf den internen unprivilegierten Benutzer foo ohne Capabilities beschränkt.
  • Ergebnis bei Anwendung von --cap-drop=all

    • Auch wenn ein rootless non-root-Container mit --cap-drop=all gestartet wird, besitzt foo ursprünglich ohnehin keine Capabilities.
    • Wird in diesem Zustand Copy Fail ausgeführt und su aufgerufen, bleibt die geöffnete Shell bei uid=1002(foo).
    • Auch in podman top bleiben /bin/bash, die Exploit-Ausführung, su, die Shell und sleep sämtlich bei foo und Capabilities none.
    • Der Exploit scheitert daran, eine root-Shell zu erlangen, und foo kann in /test nur die eigene Datei lesen.
    • Dieses Ergebnis ähnelt dem Test mit no-new-privileges; beide Maßnahmen können zusammen verwendet werden, um die Exponierung von Capabilities wirksam zu verringern.
  • Persistenz des Exploits

    • Der unmittelbare Gewinn einer root-Shell und von Capabilities konnte zwar mit no-new-privileges oder --cap-drop=all verhindert werden, die Wirkung des Exploits selbst bleibt jedoch bestehen.
    • Wird später ein neuer Container ohne Capability-Beschränkung gestartet, kann der unprivilegierte Container-Benutzer foo allein durch Aufruf von su zu Container-root werden.
    • Daher sind ein Kernel-Patch und ein Neustart weiterhin erforderlich.

Strategien zur tiefengestaffelten Verteidigung

  • Schreibgeschützte Images

    • Wenn --read-only zu podman run hinzugefügt wird, wird das Root-Dateisystem des Containers schreibgeschützt eingehängt
    • Podman bindet standardmäßig einige Verzeichnisse wie /tmp, /run und /var/tmp mit Schreibrechten ein; um den Container vollständig schreibgeschützt zu machen, muss daher auch --read-only-tmpfs=false hinzugefügt werden
    • Wird ein schreibgeschützter Container kompromittiert, sind keine Schreibzugriffe auf das System erlaubt, was einige Angriffe nach der Ausnutzung einschränken kann
    • Allerdings kann die Ausgabe von curl an python3 weitergeleitet werden, sodass die reine Schreibschutz-Konfiguration die Ausführung des Exploits selbst nicht verhindert
    • Der python3-HTTP-Server im Beispiel benötigt keine Schreibzugriffe auf das Dateisystem, sodass diese Option sicher verwendet werden kann
    • Viele vorgefertigte Images setzen Schreibzugriff auf bestimmte Verzeichnisse voraus und funktionieren mit einem schreibgeschützten Root-Dateisystem möglicherweise nicht korrekt
    • Ein schreibgeschütztes Root-Dateisystem ist unabhängig von beschreibbaren Volumes, die an den Container angebunden sind; im Fall einer Kompromittierung kann daher weiterhin in diese eingehängten Verzeichnisse geschrieben werden
  • Ressourcenlimits

    • Docker und Podman können mit cgroups die einem Container bereitgestellten Ressourcen begrenzen
    • Ein Container benötigt weder unbegrenzten Speicher noch unbegrenzte CPU- oder PID-Ressourcen
    • Mit podman stats lässt sich die Ressourcennutzung des Containers prüfen, danach können passende Limits gesetzt werden
  • Verfügbare Binärdateien begrenzen

    • Im Beispiel wird der Einfachheit halber das Image ubuntu verwendet, dieses enthält im Fall einer Kompromittierung jedoch viele Binärdateien, die ein Angreifer nutzen kann
    • Für den Betrieb des HTTP-Servers werden die meisten dieser Binärdateien nicht benötigt
    • Runtime-Images sollten möglichst schlank aufgebaut sein
    • Mit Multi-Stage-Builds lassen sich Build-Time- und Runtime-Umgebung voneinander trennen
    • Als Basis eignen sich zweckgebundene Images wie python3, Debians -slim-Varianten oder kleinere Distributionen wie alpine
    • Wenn der Containerprozess damit kompatibel ist, können distroless images oder scratch verwendet werden, um eine Runtime ohne Shell, Paketmanager und Systemwerkzeuge zu erstellen
  • Firewall

    • Mit iptables oder nftables lassen sich Containerprozesse per Firewall einschränken
    • Es sollten nur die unbedingt erforderlichen eingehenden und ausgehenden Verbindungen für den Containerprozess erlaubt werden
    • Im Beispiel des HTTP-Servers sind weder DNS noch Verbindungen zu lokalen oder entfernten Servern erforderlich, daher kann etwa auf tcp-Pakete beschränkt werden, die aus bereits aufgebauten eingehenden Verbindungen stammen

Bedeutung für den Betrieb

  • Standardmäßige Rootless-Container mit Podman bieten von Haus aus bessere Isolationsmechanismen als eine Standardkonfiguration von Docker-Containern
  • Auch Docker unterstützt Rootless-Betrieb und die Nutzung unprivilegierter User-Namespaces, benötigt dafür aber mehr Konfigurationsaufwand als Podman; zudem spielen Architekturunterschiede eine Rolle
  • Docker ist weiterhin weit verbreitet, und Self-Hosting-Tools wie Dokku, Kamal, Coolify und Dokploy verwenden standardmäßig Docker
  • Wenn Images aus Docker Hub ohne ausreichende Prüfung ausgeführt oder keine Härtungsmaßnahmen angewendet werden, kann ein Dienst mit einer größeren Angriffsfläche laufen als nötig
  • Die Implementierungsdetails von Container-Images müssen verstanden werden
    • Es muss bekannt sein, welcher Benutzer oder welche Benutzer den Containerprozess ausführen
    • Es muss bekannt sein, von welchen Verzeichnissen im Root-Dateisystem der Containerprozess abhängt
    • Es muss zwischen erforderlichen und nicht erforderlichen Linux-Capabilities unterschieden werden
  • Durch die Kombination der verschiedenen Mechanismen von Podman und Containern lassen sich Container härten und der Blast Radius im Fall einer Kompromittierung verkleinern
  • Je nach Workload sollte der Container nicht als einzige Sicherheitsgrenze betrachtet werden
  • Durch die Kombination von Containern mit separaten physischen oder virtuellen Maschinen lässt sich eine wirksame Trennung erreichen
  • Podman bietet auch auf demselben Host eine Möglichkeit zur Isolierung, indem jede Workload unter einem separaten unprivilegierten Benutzer und mit einem eigenen User-Namespace ausgeführt wird

Weiterführende Materialien

1 Kommentare

 
GN⁺ 2 시간 전
Lobste.rs-Meinungen
  • Man sollte sich eher auf das durch die Schwachstelle ermöglichte ursprüngliche Verhalten konzentrieren als auf den veröffentlichten Exploit.
    Diese Schwachstelle erlaubt Schreibzugriffe auf den Page Cache unabhängig davon, ob etwas schreibgeschützt ist. Dadurch kann ein bösartiger Container Seiten manipulieren, die zu Dateien des Base-Images von overlayfs gehören, und je nach Art der Container-Bereitstellung kann sich die Auswirkung auch auf andere Container übertragen.
    In einer rootless-Konfiguration wie hier wären andere Container betroffen, die auf dem Host-System unter demselben Benutzer laufen.
    Eine andere Exploit-Methode wäre, einen Container auf Basis eines Base-Images zu starten oder zu finden, von dem bekannt ist, dass er bereits verwendet wird, dann den Page Cache in diesem Container zu manipulieren und anschließend anderen Containern, die sich dieselbe Runtime und dieselben overlayfs-Daten teilen, die Ausführung dieses Codes unterzuschieben.
    Rootless und User Namespaces sind wichtig, helfen hier aber nicht besonders; wie auf der copy.fail-Website gesagt wird, sollte man bei Containern eher erwägen, den Systemaufruf socket(AF_ALG, ...) per seccomp zu blockieren.

    • An das zugrunde liegende ursprüngliche Verhalten hatte ich nicht so tiefgehend gedacht und mich stärker darauf konzentriert, die von rootless Containern bereitgestellten Namespaces und Capabilities zu ordnen, um die Reichweite eines kompromittierten Containers zu bewerten.
      Es wäre gut, genauer zu erläutern, was „je nach Art der Container-Bereitstellung“ konkret bedeutet.
      Ein Vorteil von rootless Podman ist, dass man je nach Workload nicht gezwungen ist, Container auf dem Host unter demselben Benutzer auszuführen.
      Wenn damit der Fall gemeint ist, mehrere rootless Container unter dem Hauptbenutzer einer Workstation laufen zu lassen, stimme ich zu; auf Servern kann man sie aber jeweils in getrennte Benutzer aufteilen, und selbst dasselbe Container-Image kann unter unterschiedlichen unprivilegierten Benutzern laufen.
      Das unterscheidet sich deutlich vom Docker-Standard, das meiste als root auszuführen, aber ich habe am Ende des Artikels auch geschrieben, dass dies keine letztgültige Sicherheitsgrenze ist und dass sich die Frage, ob rootless Container auf mehrere unprivilegierte Benutzer verteilt werden sollten, je nach Einsatzzweck unterschiedlich beantwortet.
      Bestimmte Workloads isoliere ich mit VMs.
      Ich frage mich, ob mit der Aussage, dass rootless und User Namespaces hier nicht helfen, die Verhinderung des Exploits gemeint ist.
      Mit seccomp habe ich in Containern noch keine expliziten Richtlinien verwendet, aber das ist ein guter Anlass, mich näher damit zu beschäftigen.
  • Ich mag Podman und rootless Container, aber nach CopyFail bin ich zum selben Schluss gekommen wie im benachbarten Kommentar.
    Selbst mit den zusätzlichen Vorteilen bei der Zugriffskontrolle durch podman+rootless bestätigt sich am Ende nur erneut der klassische Rat, dass Container keine Sicherheitsgrenze sind, und ein einzelner Kernel-Exploit alles durchbrechen kann.
    Ich betreibe Systemadministration nur als Hobby, aber als neuen Trend in diesem Bereich habe ich libkrun backend for crun with podman gesehen.
    Das Versprechen ist, die meisten containerisierten Workloads unverändert behandeln zu können, intern aber in einer MicroVM mit eigenem Gast-Kernel zu laufen; über Reifegrad, Praxiserprobung und Sicherheits-Audits weiß ich allerdings wenig, und manches wirkt ziemlich bleeding edge.
    Da MicroVMs von LLM-Coding-Tools aktiv übernommen werden, könnte dieser Zustand aber nicht lange anhalten.
    Auch podman machine wirkte vielversprechend, war leider aber offenbar nur für Entwickler-Workstations gedacht und folgte dem Modell, pro Host-System nur eine einzige VM für die Containerausführung zu betreiben.
    Trotzdem halte ich die Aussage „Container sind keine Sicherheitsgrenze“ für zu vereinfacht. Container sind durchaus eine Sicherheitsgrenze, nur eben keine so starke, wie wir es gern hätten.

    • Aus demselben Grund setzen die meisten Cloud-Container-Deployments auf VMs. VMs sind eine verteidigbare Grenze.
      Bei lokalen Deployments ist diese Trennlinie etwas unschärfer.
      Aus Hardware-Sicht sind VMs nicht von Natur aus sicherer als Prozesse, aber aus drei Gründen ist ihre Grenze besser verteidigbar.
      VM-Escapes sind seltener als Systemaufrufe, sodass mehr Spielraum besteht, Gegenmaßnahmen gegen Side Channels anzuwenden, ohne die Performance zu beeinträchtigen.
      Die Host-Schnittstelle einer VM ist wesentlich einfacher. Blockgeräte haben ein blockweises Lese-/Schreib-Interface, und Netzwerkgeräte senden und empfangen Frames.
      Der von Linux oder *BSD für Sockets bereitgestellte Aufruf setsockopt ist eine viel größere Angriffsfläche als die meisten Emulations- oder Paravirtualisierungstreiber, und selbst das ist nur ein sehr kleiner Teil der gesamten Kernel-Angriffsfläche.
      Auch die VM-Schnittstelle hat deutlich weniger Zustand. Es gibt Ringe mit laufenden Transaktionen im Request-Response-Modell, aber darüber hinaus fast nichts.
      Dinge wie Anmeldedaten, UID, GID und Dateideskriptortabellen fügen dem Kernel zustandsbasierte Komplexität hinzu, und bei Bugs kann ein Prozess das ausnutzen.
      Die Schwierigkeit bei der Workstation-Variante besteht darin, dass man diese Komplexität wieder einführt.
      Beispielsweise könnte die Container-Base-Layer als Blockgerät mit einem unveränderlichen Dateisystem exponiert werden, aber Volumes und geteilte Ordner würden wahrscheinlich über 9pfs oder VirtIO-FS gemountet, also 9p oder FUSE auf VirtIO.
      Damit wächst die Angriffsfläche wieder.
      Im günstigsten Fall braucht man dann eine Exploit-Kette.
      Ich kenne mich eher auf der FreeBSD-Seite aus; dort werden die Komponenten, die Paravirtualisierungs- oder Emulationsgeräte bereitstellen, üblicherweise mit Capsicum sandboxed, sodass man zuerst den Host-Prozess übernehmen und dann noch bis in den Kernel vordringen müsste, um auf etwas zuzugreifen, auf das die VM keine Berechtigung hatte.
      Ohne ein solches zusätzliches Sandboxing landet man aber wieder in einer Welt, in der ein Container-Escape alles tun kann, was der Benutzer tun kann, was auf dem Desktop kaum besser ist als ein Root-Kompromiss.
    • Kata Containers und Firecracker sind bereits ziemlich alte Technologien, und weil Forscher sie überprüft haben, würde ich sie als vernünftig ausgereift ansehen.
      Persönlich bevorzuge ich gVisor. Es ist keine VMM-Runtime, existiert aber schon seit Jahren und wird auch von Unternehmen wie Tencent eingesetzt; in meiner Umgebung, in der alle Container ohnehin bereits in Proxmox-VMs laufen, passt das gut.
      Außerdem teste ich gerade syd-oci, das im Vergleich zu den Standardempfehlungen MicroVM oder gVisor etwas weniger Beachtung gefunden zu haben scheint.
    • Diese Formulierung passt auch zu meiner Erfahrung, und das Schreiben dieses Artikels war beinahe eine Übung darin, diese Tatsache zu akzeptieren.
      Danke auch für den Verweis auf libkrun, das wirkt wie eine vielversprechende Möglichkeit.
    • Die aktive Übernahme im Bereich der LLM-Coding-Tools dürfte MicroVMs weiter reifen lassen und wahrscheinlich zu mehr Praxiserprobung und Härtung führen.
      Wahrscheinlich wird das auch zu Sicherheits-Audits führen.