
BPF-LSM-Blocker für CVE-2026-31431 (Copy Fail) – Remediation ohne Neustart für OpenShift 4
CVE-2026-31431 („Copy Fail") ist eine Privilege-Escalation-Schwachstelle im Linux-Kernel
in der kryptografischen Schnittstelle algif_aead. Ein Angreifer nutzt AF_ALG-Sockets mit
dem Algorithmus authencesn und splice(), um beliebige Dateien im Kernel-Page-Cache
zu korrumpieren – einschließlich setuid-Binaries wie /usr/bin/su.
Dieses Dokument bietet eine Remediation ohne Neustart mithilfe eines BPF-LSM-DaemonSets,
das alle AF_ALG-AEAD-Bindings blockiert – die Subsystem-Komponente, die von Copy Fail ausgenutzt wird.
Dies verhindert Umgehungen über Crypto-Template-Verschachtelung (z. B. pcrypt(authencesn(...))).
Andere AF_ALG-Nutzungen (Hash, Skcipher) bleiben unberührt. Ende-zu-Ende auf drei
separaten OCP-4.22-Clustern getestet.
# 1. Prüfen, ob BPF LSM aktiviert ist (RHEL CoreOS 9.8 hat es standardmäßig)
oc debug node/<any-node> -- chroot /host cat /sys/kernel/security/lsm
# Muss "bpf" enthalten
# 2. Namespace bereitstellen und privilegiertes SCC gewähren
oc apply -f daemonset.yaml
# 3. DaemonSet-Pods starten automatisch auf allen Knoten
# 4. Verifizieren
oc get pods -n block-copyfail # Alle Knoten sollten Running anzeigen
oc logs -n block-copyfail -l app=block-copyfail
# Erwartet: "block-copyfail: blocker active — all AF_ALG AEAD binds blocked"
Keine Neustarts. Keine Node-Drains. Keine Pod-Neustarts. Der Schutz ist sofort aktiv und deckt alle Prozesse auf allen Knoten ab (100 % Abdeckung).
Der Exploit verkettet drei Kernel-Funktionen:
socket(AF_ALG, SOCK_SEQPACKET, 0)authencesn(hmac(sha256),cbc(aes)), einen spezifischen
authentifizierten VerschlüsselungsalgorithmusDer Angreifer korrumpiert /usr/bin/su im Page-Cache (ohne Schreibzugriff auf die
Datei) und führt es dann aus, um Root-Rechte zu erlangen.
Erstellen Sie einen neuen cve-2026-31431-test-Namespace auf Ihrem Cluster und führen Sie das Testskript aus, indem Sie die Manifests im Verzeichnis test anwenden:
oc apply -f test
Prüfen Sie die Ergebnisse:
oc wait pod/cve-test -n cve-2026-31431-test \
--for=jsonpath='{.status.phase}'=Succeeded --timeout=120s
oc -n cve-2026-31431-test logs -l app=cve-2026-31431-test
Auf einem verwundbaren Cluster sehen Sie:
=== CVE-2026-31431 Vulnerability Test ===
Target: /usr/bin/su
Original SHA256: 8969560ae8e6e21c6184c1451f59418822ee69dd5d946d71987b55236bbc0feb
Attempting splice + AF_ALG page-cache corruption (160 bytes in 40 chunks)...
After SHA256: 30b0f5b5a054c4df65b48ca792863bf7054b4d793f15f57163792ba6c2b151ae
PAGE CACHE CORRUPTION: YES - /usr/bin/su was modified in the page cache
Attempting to execute corrupted /usr/bin/su ...
exit code: 0
RESULT: PARTIALLY MITIGATED
Page-cache corruption succeeded (kernel is vulnerable)
Privilege escalation blocked (allowPrivilegeEscalation=false)
oc delete namespace cve-2026-31431-test
Der BPF-LSM-Ansatz hakt socket_bind auf Kernel-Ebene ein und blockiert alle
AF_ALG-AEAD-Bindings unabhängig von der Template-Verschachtelung. Er basiert auf
block-copyfail, neu geschrieben in C
mit libbpf für die OCP-Bereitstellung.
BPF LSM muss aktiviert sein. RHEL CoreOS 9.8 (OCP 4.22) hat es standardmäßig aktiviert. Überprüfen mit:
oc debug node/<any-node> -- chroot /host cat /sys/kernel/security/lsm
Die erwartete Ausgabe enthält bpf:
lockdown,capability,landlock,yama,selinux,bpf
Wenn bpf nicht vorhanden ist, ist eine einmalige MachineConfig erforderlich (dies ist
das einzige Szenario, das einen Neustart erfordert):
apiVersion: machineconfiguration.openshift.io/v1
kind: MachineConfig
metadata:
labels:
machineconfiguration.openshift.io/role: worker
name: 99-enable-bpf-lsm
spec:
kernelArguments:
- lsm=lockdown,capability,selinux,bpf
Erstellen Sie einen neuen block-copyfail-Namespace, gewähren Sie SCC und stellen Sie das DaemonSet bereit, indem Sie das daemonset.yaml-Manifest anwenden.
Das privilegierte SCC muss gewährt werden, bevor die DaemonSet-Pods erstellt werden,
andernfalls schlägt die Pod-Erstellung mit SCC-Validierungsfehlern fehl.
oc apply -f daemonset.yaml
oc get pods -n block-copyfail -o wide
Erwartet: ein Pod pro Knoten, alle Running:
NAME READY STATUS AGE NODE
block-copyfail-2jhzf 1/1 Running 34s ci-...-master-2
block-copyfail-4dfq7 1/1 Running 34s ci-...-master-1
block-copyfail-c2ts8 1/1 Running 34s ci-...-worker-c
block-copyfail-ctblk 1/1 Running 34s ci-...-worker-a
block-copyfail-m26sx 1/1 Running 34s ci-...-worker-b
block-copyfail-xsh6d 1/1 Running 34s ci-...-master-0
oc logs -n block-copyfail -l app=block-copyfail
Erwartet:
block-copyfail: blocker active — all AF_ALG AEAD binds blocked
Führen Sie denselben Exploit-Test aus dem Abschnitt Schwachstelle bestätigen erneut aus.
Nach der Bereitstellung des BPF-LSM-DaemonSets sieht die Ausgabe wie folgt aus:
=== CVE-2026-31431 Vulnerability Test ===
Target: /usr/bin/su
Original SHA256: 30b0f5b5a054c4df65b48ca792863bf7054b4d793f15f57163792ba6c2b151ae
Attempting splice + AF_ALG page-cache corruption (160 bytes in 40 chunks)...
AF_ALG bind failed: [Errno 1] Operation not permitted
RESULT: CANNOT TEST - AF_ALG or splice not available/permitted
Die DaemonSet-Logs zeigen den blockierten Versuch:
oc logs -n block-copyfail -l app=block-copyfail
block-copyfail: blocker active — all AF_ALG AEAD binds blocked
block-copyfail: BLOCKED pid=16777 comm=python3 time=2026-05-01 16:37:23
Führen Sie verify-algos.py auf einem Knoten aus, um zu bestätigen, dass alle AEAD-Algorithmen blockiert sind,
während andere AF_ALG-Typen (Hash, Skcipher) weiterhin funktionieren:
oc debug node/<any-node> -- chroot /host python3 -c "
import socket
tests = [
('aead', 'gcm(aes)'),
('aead', 'ccm(aes)'),
('aead', 'rfc4106(gcm(aes))'),
('hash', 'sha256'),
('skcipher', 'cbc(aes)'),
('aead', 'authencesn(hmac(sha256),cbc(aes))'),
]
for t, n in tests:
s = socket.socket(socket.AF_ALG, socket.SOCK_SEQPACKET, 0)
try:
s.bind((t, n))
print(f' ALLOWED {t}/{n}')
except OSError as e:
print(f' BLOCKED {t}/{n} -- {e}')
finally:
s.close()
"
Erwartete Ausgabe:
BLOCKED aead/gcm(aes) -- [Errno 1] Operation not permitted
BLOCKED aead/ccm(aes) -- [Errno 1] Operation not permitted
BLOCKED aead/rfc4106(gcm(aes)) -- [Errno 1] Operation not permitted
ALLOWED hash/sha256
ALLOWED skcipher/cbc(aes)
BLOCKED aead/authencesn(hmac(sha256),cbc(aes)) -- [Errno 1] Operation not permitted
Dies bestätigt, dass der BPF-LSM alle AEAD-Bindings blockiert, während andere AF_ALG-Typen funktionsfähig bleiben.
Der Quellcode des BPF-LSM-Blockers befindet sich in block-copyfail/:
block-copyfail/
block_copyfail.bpf.c # BPF-Kernelprogramm (LSM-Hook)
block_copyfail.c # Userspace-Loader (libbpf-Skeleton)
block_copyfail.h # Gemeinsame Event-Struktur
Makefile # Build-Pipeline
Dockerfile # Multi-Stage-Build
daemonset.yaml # Namespace- + DaemonSet-Manifest
trigger-test.py # Schnelles Validierungsskript
Build und Push:
cd block-copyfail/
podman build -t quay.io/<org>/block-copyfail:latest .
podman push quay.io/<org>/block-copyfail:latest
Das Dockerfile verwendet einen Multi-Stage-Build: Fedora mit clang/bpftool/libbpf-devel für die Kompilierung, UBI 9 minimal für das Laufzeit-Image (~122 MB).
Das Löschen des DaemonSets entfernt die Abschwächung sofort auf allen Knoten:
oc delete -f daemonset.yaml
# oder
oc delete namespace block-copyfail
Das BPF-Programm wird automatisch getrennt, wenn der Loader-Prozess beendet wird. Kein Neustart oder Pod-Neustart ist erforderlich.