
AF_ALG/splice 기반 Linux Page Cache 변조 취약점 분석 및 대응 실습
Dieses Projekt analysiert die Funktionsweise der Linux-Kernel-Sicherheitslücke Copy Fail (CVE-2026-31431) und vergleicht den Zustand vor und nach dem Patch mit Hilfe des nicht-destruktiven Checkers aus dem öffentlichen PoC-Repository.
Es führt keine tatsächliche Manipulation von setuid-Binärdateien oder der /etc/passwd-Datei durch, sondern konzentriert sich auf die sichere Überprüfung der Anfälligkeit auf Basis einer temporären testfile sowie auf die Analyse aus Erkennungs- und Abmilderungsperspektive.
Ziel dieses Projekts ist es nicht, einfach einen Exploit auszuführen, sondern zu verstehen, aus welcher Kombination interner Strukturen eine Linux-Kernel-Sicherheitslücke entsteht, und zusammenzufassen, wie sie aus betrieblicher Sicht erkannt und behoben werden kann.
Der Umfang ist wie folgt:
Analyse des Schwachstellenprinzips
↓
Analyse der PoC-Codestruktur
↓
Übung mit nicht-destruktivem Checker
↓
Vergleich vor/nach dem Patch
↓
Zusammenfassung der Erkennungs-/Abmilderungsmaßnahmen
In dieser Übung wurde nur vulnerable.c aus dem Repository copy-fail-c ausgeführt.
Kernelinformationen vor dem Patch:
Linux ubuntu-server 6.8.0-53-generic #55-Ubuntu SMP PREEMPT_DYNAMIC Fri Jan 17 15:37:52 UTC 2025 x86_64 x86_64 x86_64 GNU/Linux
Kernelinformationen nach dem Patch:
Linux ubuntu-server 6.8.0-134-generic #134-Ubuntu SMP PREEMPT_DYNAMIC Fri Jun 26 18:43:11 UTC 2026 x86_64 x86_64 x86_64 GNU/Linux
Zusammenfassung der Kernel-Paketänderungen:
- linux-image-6.8.0-53-generic 6.8.0-53.55
- linux-image-generic 6.8.0-53.55+1
+ linux-image-6.8.0-134-generic 6.8.0-134.134
+ linux-image-generic 6.8.0-134.134
+ linux-generic 6.8.0-134.134
+ linux-headers-generic 6.8.0-134.134
Copy Fail ist eine Sicherheitslücke, die durch die Kombination des AF_ALG-AEAD-Verarbeitungspfads im Linux-Kernel mit dem splice()-Zero-Copy-Mechanismus entsteht, wodurch der Page-Cache einer schreibgeschützten Datei fälschlicherweise als Schreibziel verwendet werden kann.
Die Kernkomponenten sind:
Der Kernfluss der Sicherheitslücke ist:
Lesbare Datei
↓
Wird in den Linux Page Cache geladen
↓
Übergabe des Page-Cache-Referenz über splice() an den AF_ALG-Crypto-Pfad
↓
Durch AEAD-In-Place-Verarbeitung werden Eingabe- und Ausgabe-Scatterlist verknüpft
↓
Während der authencesn-Verarbeitung tritt ein 4-Byte-Scratch-Schreibzugriff auf
↓
Schreibzugriff erfolgt nicht in einen separaten Ausgabepuffer, sondern in den Page Cache
↓
Page-Cache-Mutation tritt auf
Das heißt: splice() übergibt die Page-Cache-Referenz, die AEAD-In-Place-Verarbeitung verknüpft Eingabe und Ausgabe über denselben Pfad, und authencesn löst den tatsächlichen 4-Byte-Schreibzugriff aus.
Die Struktur des in der Übung verwendeten Repositorys ist wie folgt:
copy-fail-c/
├── exploit.c
├── exploit-passwd.c
├── vulnerable.c
├── payload.c
├── utils.c
├── utils.h
├── Makefile
└── nolibc/
utils.cDer Kern von utils.c ist das Page-Cache-Mutation-Primitive der patch_chunk()-Familie. Diese Funktion verbindet den Page-Cache der Zieldatei über AF_ALG und splice() mit dem Crypto-Verarbeitungspfad und prüft bei anfälligen Kerneln, ob während der AEAD-Verarbeitung ein Teil des Page-Cache überschrieben wird.
vulnerable.cvulnerable.c greift nicht auf tatsächliche Systemdateien zu. Es erstellt eine temporäre testfile im aktuellen Verzeichnis und prüft, ob deren Page-Cache manipuliert wird.
In diesem Projekt wurde nur diese Datei ausgeführt.
Vor dem Kernel-Update wurden Betriebssystem-, Kernel- und Paketstatus aufgezeichnet.
mkdir -p ~/copyfail-mini/{before,after,logs}
cd ~/copyfail-mini
uname -a | tee before/uname.txt
cat /etc/os-release | tee before/os-release.txt
dpkg -l | grep -E 'linux-image|linux-headers|linux-generic|linux-virtual' | tee before/kernel-package.txt
git clone https://github.com/jihwan77/copy-fail-c.git
cd copy-fail-c
make clean
make vulnerable
In dieser Übung wurde nicht der vollständige make-Befehl zum Bau aller Exploit-Binärdateien verwendet, sondern nur das Ziel vulnerable.
./vulnerable > ../before/vulnerable-output.txt 2>&1
echo $? >> ../before/vulnerable-output.txt
cat ../before/vulnerable-output.txt
Ausgabe vor dem Patch:

Beurteilung:
exit code 100
→ Page-Cache-Mutation bestätigt
→ Funktionsweise des Copy-Fail-Primitives im Kernel vor dem Patch bestätigt
Nachdem die Ergebnisse vor dem Patch gespeichert wurden, wurde ein Ubuntu-Paketupdate durchgeführt.
sudo apt update
sudo apt full-upgrade -y
sudo reboot
Nach dem Neustart änderte sich der Kernel wie folgt:
Vorher: 6.8.0-53-generic
Nachher: 6.8.0-134-generic
cd ~/copyfail-mini/copy-fail-c
make clean
make vulnerable
./vulnerable > ../after/vulnerable-output.txt 2>&1
echo "exit_code=$?" >> ../after/vulnerable-output.txt
cat ../after/vulnerable-output.txt
Ausgabe nach dem Patch:

Ergebnisvergleich:
exit_code=2 nach dem Patch bedeutet nicht einfach „nicht anfällig“. Genauer gesagt:
Das authencesn(hmac(sha256),cbc(aes))-Template von AF_ALG ist nicht registriert,
sodass der Checker die Anfälligkeit nicht direkt feststellen konnte.
Eine zusätzliche Überprüfung ergab, dass nach dem Ubuntu-Update das Laden des Moduls algif_aead blockiert war.
lsmod | grep -E 'af_alg|algif_aead'
Ergebnis:
af_alg 32768 0
algif_aead war nicht geladen.
sudo modprobe algif_aead
Ergebnis:
modprobe: ERROR: ../libkmod/libkmod-module.c:1084 command_do() Error running install command '/bin/false' for module algif_aead: retcode 1
modprobe: ERROR: could not insert 'algif_aead': Invalid argument
Überprüfung der Sperrkonfiguration:
grep -R "algif_aead" /etc/modprobe.d /lib/modprobe.d 2>/dev/null
Ergebnis:
/etc/modprobe.d/disable-aligf_aead.conf:# Disable algif_aead module due to CVE-2026-31431 (AKA copy.fail)
/etc/modprobe.d/disable-aligf_aead.conf:install algif_aead /bin/false
Daher ist das Ergebnis nach dem Patch wie folgt zu interpretieren:
Nach dem Ubuntu-Sicherheitsupdate wurde der Kernel auf 6.8.0-134-generic aktualisiert,
und es wurde eine Abmilderung durch Blockierung des kmod-basierten algif_aead-Moduls angewendet.
Infolgedessen konnte der vulnerable-Checker von copy-fail-c
das vom PoC benötigte AF_ALG-Template authencesn(hmac(sha256),cbc(aes)) nicht binden,
und die Page-Cache-Mutationsstufe wurde nicht erreicht.
Das heißt, in dieser Übung wurde nicht nur der „Effekt des Kernel-Code-Patches“ bestätigt, sondern vielmehr der Zustand, dass nach dem Ubuntu-Sicherheitsupdate der Kernel aktualisiert und die Sperre des algif_aead-Moduls angewendet wurde, sodass derselbe PoC-Pfad nicht fortgesetzt wurde.
Da Copy Fail den Diskcache manipuliert, ohne die Datei auf der Festplatte direkt zu ändern, sind dateihashbasierte Erkennungsmethoden nur begrenzt einsetzbar. Daher ist die Erkennung auf Basis von Syscall-Verhalten wichtig.
In dieser Übung wurden mit auditd die folgenden Syscalls beobachtet:
sudo auditctl -a always,exit -F arch=b64 -S socket -F a0=38 -k copyfail_afalg
sudo auditctl -a always,exit -F arch=b64 -S bind -k copyfail_bind
sudo auditctl -a always,exit -F arch=b64 -S splice -k copyfail_splice
sudo auditctl -a always,exit -F arch=b64 -S sendmsg -k copyfail_sendmsg
socket(AF_ALG)In den Logs wurde bestätigt, dass der Prozess vulnerable einen AF_ALG-Socket erstellt hat.
comm=vulnerable
syscall=socket
success=yes
a0=alg
key=copyfail_afalg
bind()In der Umgebung nach dem Patch / nach der Abmilderung versuchte der vulnerable-Prozess, sich an das authencesn-Template zu binden, scheiterte jedoch.
comm=vulnerable
syscall=bind
success=no
exit=ENOENT(No such file or directory)
saddr_fam=alg
key=copyfail_bind
Dies bedeutet, dass der PoC in der Umgebung nach dem Patch zwar den AF_ALG-Socket erstellte, aber beim Binden des Templates authencesn(hmac(sha256),cbc(aes)) scheiterte.
splice()- / sendmsg()-LogsDa der bind()-Schritt nach dem Patch fehlschlug, erreichte der Checker die splice()- und sendmsg()-Stufen nicht. Daher wurden in den entsprechenden Syscall-Logs keine signifikanten Ausführungsflüsse von vulnerable beobachtet.
Bei der Beobachtung von Copy-Fail-ähnlichen Sicherheitslücken in einer Produktionsumgebung können die folgenden Aktionskombinationen auftreten:
In dieser Übung wurden das Ereignis socket(AF_ALG) und das fehlgeschlagene bind()-Ereignis mit auditd bestätigt.
Die grundlegendste Maßnahme ist die Anwendung von Sicherheitsupdates der Distribution.
sudo apt update
sudo apt full-upgrade -y
sudo reboot
In dieser Übung wurde nach dem Update die Umgebung auf Ubuntu 24.04.4 / Kernel 6.8.0-134-generic umgestellt.
algif_aeadNach dem Ubuntu-Update wurde die folgende Konfiguration bestätigt:
/etc/modprobe.d/disable-aligf_aead.conf
install algif_aead /bin/false
Diese Konfiguration blockiert das Laden des Moduls algif_aead und verhindert so den vom PoC benötigten Eintritt in den AF_ALG-AEAD-Pfad.
Da normale Serveranwendungen AF_ALG in der Regel nicht direkt verwenden, kann der Aufruf von socket(AF_ALG) als Erkennungspunkt genutzt werden.
Die Ergebnisse dieser Übung können wie folgt zusammengefasst werden:
Vor dem Patch:
Ubuntu 24.04.2 / Kernel 6.8.0-53-generic
vulnerable Checker Exit-Code 100
Page-Cache-Mutation bestätigt
→ Funktionsweise des Copy-Fail-Primitives bestätigt
Nach dem Patch:
Ubuntu 24.04.4 / Kernel 6.8.0-134-generic
vulnerable Checker Exit-Code 2
Authencesn-Template-Bind fehlgeschlagen
Bestätigung der Blockierung des algif_aead-Moduls
→ Derselbe PoC-Pfad erreicht die Page-Cache-Mutationsstufe nicht
Daher lautet die Schlussfolgerung dieses Projekts:
Im Kernel vor dem Patch funktionierte das Page-Cache-Mutation-Primitive von Copy Fail tatsächlich. Nach der Anwendung des Ubuntu-Sicherheitsupdates wurde der Kernel auf
6.8.0-134-genericaktualisiert und eine offenbar kmod-basierte Sperrkonfiguration für dasalgif_aead-Modul angewendet. Infolgedessen konnte der PoC das erforderlicheauthencesn(hmac(sha256),cbc(aes))-AF_ALG-Template nicht binden, sodass derselbe Checker die Page-Cache-Mutationsstufe nicht erreichte.
Das heißt, in den Ergebnissen dieser Übung kann nicht gesagt werden, dass „der Kernel-Code-Patch selbst die Page-Cache-Mutation direkt blockiert hat“, aber aufgrund der bisherigen Logs und Ergebnisse kann eindeutig gesagt werden: Nach dem Ubuntu-Sicherheitsupdate wurde die Abmilderung durch Blockierung des algif_aead-Moduls angewendet, wodurch der PoC-Pfad blockiert wurde.
Ubuntu Security Notice - USN-8226-1: kmod update
https://ubuntu.com/security/notices/USN-8226-1
Ubuntu Blog - Fixes available for CVE-2026-31431 Copy Fail
https://ubuntu.com/blog/copy-fail-vulnerability-fixes-available
copy-fail-c PoC Repository
https://github.com/jihwan77/copy-fail-c
Die wichtigsten Erkenntnisse aus diesem Projekt sind:
1. Copy Fail ist eine Kernel-Sicherheitslücke, die AF_ALG, splice(), AEAD-In-Place, authencesn und Page Cache kombiniert.
2. In der Umgebung vor dem Patch (Ubuntu 24.04.2 / Kernel 6.8.0-53) bestätigte der nicht-destruktive Checker eine Page-Cache-Mutation.
3. In der Umgebung nach dem Patch (Ubuntu 24.04.4 / Kernel 6.8.0-134) scheiterte der Checker beim Binden von authencesn.
4. Eine zusätzliche Überprüfung ergab, dass das Laden des Moduls algif_aead durch die Konfiguration /bin/false blockiert wurde.
5. Mit auditd konnten die Ereignisse socket(AF_ALG) und fehlgeschlagenes bind beobachtet werden.
6. Betriebliche Gegenmaßnahmen umfassen: Kernel-/Sicherheitspaket-Updates, Einschränkung von algif_aead, Überwachung von AF_ALG-Syscalls und Überprüfung von setuid-Binärdateien.
| Bereich | Vor dem Patch | Nach dem Patch |
|---|
| OS | Ubuntu 24.04.2 LTS | Ubuntu 24.04.4 LTS |
| Kernel | 6.8.0-53-generic | 6.8.0-134-generic |
| Benutzerkonto | Normaler Benutzer client | Normaler Benutzer client |
| Checker | vulnerable | vulnerable |
| Testmethode | Nicht-destruktive Prüfung basierend auf temporärer testfile | Erneute Ausführung desselben Checkers |
| Element | Rolle |
|---|
| Linux Page Cache | Kernel-Mechanismus zum Cachen von Dateiinhalten von der Festplatte im RAM |
splice() | Zero-Copy-Syscall, der Daten ohne Kopie in den Benutzerbereich als Referenz innerhalb des Kernels verbindet |
AF_ALG | Schnittstelle, die es dem Benutzerbereich ermöglicht, die Kernel-Crypto-API wie einen Socket zu verwenden |
| AEAD-In-Place-Verarbeitung | Optimierung, bei der der Eingabe- und Ausgabepuffer nicht getrennt, sondern im selben Puffer verarbeitet werden |
authencesn | Crypto-Template, das während der AEAD-Verarbeitung einen 4-Byte-Scratch-Schreibzugriff erzeugt |
| Datei | Rolle | Verwendung in dieser Übung |
|---|
utils.c, utils.h | Implementierung des Page-Cache-Mutation-Primitives basierend auf AF_ALG/splice | Verwendet für Analyse und Ausführung von vulnerable |
vulnerable.c | Nicht-destruktives Tool zur Überprüfung der Anfälligkeit basierend auf temporärer testfile | Ausgeführt |
exploit.c | Variante zur Manipulation des Page-Cache einer setuid-root-Binärdatei | Nicht ausgeführt |
exploit-passwd.c | Variante zur Manipulation des Page-Cache von /etc/passwd | Nicht ausgeführt |
payload.c | Payload, die mit Root-Rechten ausgeführt wird | Nicht ausgeführt |
Makefile | Build-Automatisierung | Nur vulnerable-Target verwendet |
nolibc/ | Leichte libc-Alternative zum Bau kleiner statischer ELF-Payloads | Nur Analyse |
| Punkt | Vor dem Patch | Nach dem Patch |
|---|
| Kernel | 6.8.0-53-generic | 6.8.0-134-generic |
| Checker-Ergebnis | VULNERABLE | authencesn template not registered |
| Exit-Code | 100 | 2 |
| Page-Cache-Mutation | Bestätigt | Checker erreicht die Mutationsstufe nicht |
| Interpretation | Copy-Fail-Primitive funktioniert | PoC kann den erforderlichen AEAD/authencesn-Pfad nicht betreten |
| Erkennungsziel | Bedeutung |
|---|
socket(AF_ALG, ...) | Versuch, die Kernel-Crypto-API zu verwenden |
bind() mit authencesn | Versuch, das AEAD/authencesn-Crypto-Template zu verwenden |
splice() | Übergabe einer Datei-Page-Cache-Referenz an einen internen Kernel-Pfad |
sendmsg() / recvmsg() | Ausführung einer AF_ALG-Crypto-Anfrage |
| Ausführung einer setuid-Binärdatei | Möglichkeit der Privilegieneskalation (Cashout) |