
Docker-Mitigation für CVE-2026-31431 („Copy Fail“). Enthält auch Kubernetes-Vorlagen.
Idempotentes Skript, um die Erstellung von AF_ALG-Sockets für alle Docker-Container
auf einem Host zu blockieren, als Abschwächung für CVE-2026-31431 („Copy Fail").
CVE-2026-31431 ist eine lokale Privilegieneskalation in der kryptografischen
authencesn-Vorlage des Linux-Kernels, die in Kernen vorhanden ist, die zwischen 2017 und
der Verfügbarkeit des Upstream-Fixes (Mainline-Commit a664bf3d603d) gebaut wurden. Ein
unprivilegierter Benutzer kann eine AF_ALG-Socket-Operation mit splice() verketten, um
einen kontrollierten 4-Byte-Schreibvorgang in den Page-Cache einer beliebigen lesbaren Datei
durchzuführen, die auf ein setuid-Binärprogramm abzielt, um eine Root-Shell zu erhalten. Ein
732-Byte-Python-Proof-of-Concept nutzt dies zuverlässig aus, ohne Races oder
distributionsspezifische Offsets, auf jeder großen Linux-Distribution, die einen betroffenen
Kernel ausliefert.
Der obligatorische erste Schritt des Exploits ist das Öffnen eines AF_ALG-Sockets
(socket(AF_ALG, SOCK_SEQPACKET, 0)). Das Blockieren dieses Syscalls über seccomp
verhindert die Ausnutzung selbst auf ungepatchten Kernen. Das in Docker integrierte
Standard-seccomp-Profil blockiert AF_ALG nicht, und RuntimeDefault ist nicht
ausreichend — getestete Cluster zeigten, dass Pods, die unter PSS Restricted zugelassen
wurden, weiterhin AF_ALG-Sockets öffnen konnten.
Siehe die ursprüngliche Forscher-Beratung unter https://copy.fail und die CERT-EU- Beratung unter https://cert.europa.eu/publications/security-advisories/2026-005/ für vollständige technische Details und Patch-Verfügbarkeit nach Distribution.
Dieses Skript deckt die globale Daemon-Konfiguration der Docker Engine ab. Für
Kubernetes siehe den Kubernetes-Abschnitt unten. Für Bare-Metal- oder
VM-Workloads (nicht containerisiert) deaktivieren Sie stattdessen das Kernelmodul algif_aead:
echo "install algif_aead /bin/false" > /etc/modprobe.d/disable-algif.conf
rmmod algif_aead 2>/dev/null || true
Dieser Ansatz hat keine Auswirkungen auf dm-crypt/LUKS, kTLS, IPsec/XFRM, OpenSSL, GnuTLS, NSS oder SSH.
Extrahiert Docks aktives integriertes seccomp-Profil, indem es die
HostConfig.SecurityOpt eines kurzlebigen Containers inspiziert. Dies vermeidet jede
Abhängigkeit von einer entfernten URL und garantiert, dass das Basisprofil mit der
tatsächlich installierten Docker-Version übereinstimmt. Ein GitHub-Abruf von
moby/profiles wird nur als Fallback verwendet,
wenn die Container-Inspektion nichts ergibt.
Patched das Profil, indem socket aus dem Allowlist-Eintrag von Docker entfernt
und mit einem Argumentfilter wieder hinzugefügt wird, der alle Adressfamilien außer
AF_ALG (Wert 38) unter Verwendung von SCMP_CMP_NE zulässt. Das gesamte übrige
Standard-seccomp-Verhalten von Docker bleibt erhalten.
Schreibt das gepatchte Profil atomar nach
/etc/seccomp/docker-block-af-alg.json (Temp-Datei + Umbenennung). Übersprungen, wenn
der Inhalt auf der Festplatte bereits identisch ist.
Aktualisiert /etc/docker/daemon.json, um "seccomp-profile" auf den Pfad des
gepatchten Profils zu setzen. Die Originaldatei wird bei der ersten Änderung als
daemon.json.bak gesichert. Übersprungen, wenn bereits korrekt konfiguriert.
Lädt dockerd neu über systemctl reload docker (SIGHUP — kein Neustart
erforderlich). Übersprungen, wenn keine der Dateien geändert wurde.
Verifiziert, dass der Block aktiv ist, indem ein Probe innerhalb eines Containers ausgeführt wird, unabhängig davon, ob in den obigen Schritten Änderungen vorgenommen wurden.
Das Skript ist idempotent: Mehrfaches Ausführen erzeugt dasselbe Ergebnis und lädt Docker nur neu, wenn sich tatsächlich etwas geändert hat.
Hinweis:
--privileged-Container umgehen alle seccomp-Profile unabhängig von dieser Konfiguration. Prüfen Sie Ihre Compose-Dateien und führen Sie Befehle für privilegierte Container separat aus.
docker-CLI im PATHcurl im PATH (nur Fallback)systemctl (systemd-Host)/etc/seccomp und /etc/docker sowie für
systemctl reload docker# Abschwächung anwenden und verifizieren (normale Verwendung)
sudo python3 harden-docker-seccomp.py
# Anzeigen, was sich ändern würde, ohne etwas zu schreiben oder Docker neu zu laden
sudo python3 harden-docker-seccomp.py --dry-run
# Nur die Container-Verifizierung erneut ausführen (keine Konfigurationsänderungen)
python3 harden-docker-seccomp.py --verify-only
# Ausführliche Ausgabe
sudo python3 harden-docker-seccomp.py --verbose
INFO Written: /etc/seccomp/docker-block-af-alg.json
INFO Updated: /etc/docker/daemon.json
INFO Reloading Docker daemon (SIGHUP)…
INFO Docker daemon reloaded.
INFO Verifying AF_ALG is blocked inside a container…
OK: AF_ALG blocked — [Errno 1] Operation not permitted
INFO All done. CVE-2026-31431 (Copy Fail) mitigation is active.
INFO Profile unchanged: /etc/seccomp/docker-block-af-alg.json
INFO daemon.json already configured correctly.
INFO No changes — Docker daemon reload not required.
INFO Verifying AF_ALG is blocked inside a container…
OK: AF_ALG blocked — [Errno 1] Operation not permitted
INFO All done. CVE-2026-31431 (Copy Fail) mitigation is active.
| Code | Bedeutung |
|---|---|
0 | Erfolg — Abschwächung ist aktiv |
1 | Skript nicht als Root ausgeführt (beim Patchen) oder nicht behebbarer Fehler |
2 | Verifizierung fehlgeschlagen — AF_ALG ist nicht blockiert |
Kubernetes-Pods teilen sich den Host-Kernel, daher ist dieselbe AF_ALG-Socket-Primitive
von jedem Pod auf einem betroffenen Knoten erreichbar. RuntimeDefault-seccomp ist nicht
ausreichend — getestete Cluster zeigten, dass Pods, die unter PSS Restricted zugelassen
wurden, weiterhin AF_ALG-Sockets öffnen konnten. Ein Localhost-Profil mit einer
expliziten Deny-Regel ist erforderlich.
Die Abschwächung erfordert zwei Dinge: die Profil-JSON auf dem Dateisystem jedes Knotens und jede Pod-Spezifikation, die darauf verweist. Die folgenden Abschnitte behandeln beides, einschließlich der globalen Injektion des Profils ohne Änderung einzelner Pod-Spezifikationen.
Der Kubelet löst Localhost-seccomp-Profile relativ zu seinem seccomp-
Root auf, der standardmäßig /var/lib/kubelet/seccomp ist. Das Profil muss an
diesem Pfad auf jedem Knoten vorhanden sein, der einen Workload planen kann.
Wenden Sie das ConfigMap und das DaemonSet aus diesem Repository an:
kubectl apply -f templates/configmap-seccomp-profile.yaml
kubectl apply -f templates/daemonset-distribute-profile.yaml
Das DaemonSet führt einen Init-Container aus, der das Profil aus dem ConfigMap in den seccomp-Root des Knotens kopiert und dann einen minimalen Pause- Container parkt, sodass der Pod für die Gesundheitsüberwachung sichtbar bleibt. Es toleriert alle Taints, sodass es auch auf Control-Plane-Knoten läuft.
Nicht standardmäßiger Kubelet-seccomp-Root: RKE2 verwendet
/var/lib/rancher/rke2/agent/kubelet/seccomp. Überschreiben Sie den Pfad, indem SieNODE_SECCOMP_ROOTin der Umgebung des Init-Containers des DaemonSets setzen, bevor Sie es anwenden.
Verifizieren Sie, dass die Datei auf einem Knoten vorhanden ist:
kubectl -n kube-system exec -it \
$(kubectl -n kube-system get pod -l app.kubernetes.io/name=distribute-af-alg-seccomp \
-o jsonpath='{.items[0].metadata.name}') -- \
cat /var/lib/kubelet/seccomp/block-af-alg.json