
Analyse et atténuation de la vulnérabilité Copy Fail du noyau Linux (CVE-2026-31431) exploitant la mutation du cache de pages AF_ALG/splice, avec un vérificateur de preuve de concept (PoC), des règles de détection auditd et une vérification de mise à jour du noyau.
Ce projet est un mini-projet qui analyse le principe de fonctionnement de la vulnérabilité Copy Fail (CVE-2026-31431) du noyau Linux et compare l’état avant et après le patch à l’aide du checker non destructif du dépôt PoC public.
Aucun exploit réel de modification de binaires setuid ou de /etc/passwd n’est effectué ; l’accent est mis sur la vérification sécurisée de la vulnérabilité basée sur un testfile temporaire et sur l’analyse du point de vue de la détection et de l’atténuation.
L’objectif de ce projet n’est pas simplement d’exécuter un exploit, mais de comprendre comment une vulnérabilité du noyau Linux se produit par la combinaison de structures internes et de déterminer comment la vérifier et y répondre d’un point de vue opérationnel.
Le périmètre est le suivant :
Analyse du principe de la vulnérabilité
↓
Analyse de la structure du code PoC
↓
Exercice pratique basé sur un checker non destructif
↓
Comparaison avant et après le patch
↓
Synthèse des mesures de détection/atténuation
Dans cet exercice, seul du dépôt a été exécuté.
vulnerable.ccopy-fail-c| Catégorie | Avant le patch | Après le patch |
|---|---|---|
| OS | Ubuntu 24.04.2 LTS | Ubuntu 24.04.4 LTS |
| Noyau | 6.8.0-53-generic | 6.8.0-134-generic |
| Compte | Utilisateur normal client | Utilisateur normal client |
| Checker | vulnerable | vulnerable |
| Méthode de test | Vérification non destructive basée sur testfile temporaire | Réexécution du même checker |
Informations sur le noyau avant le 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
Informations sur le noyau après le 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
Résumé des modifications des paquets du noyau :
- 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 est une vulnérabilité qui survient lorsque le chemin de traitement AEAD de AF_ALG du noyau Linux est combiné avec le comportement zero-copy de splice(), permettant au cache de pages d’un fichier en lecture seule d’être utilisé abusivement comme cible d’écriture.
Les composants clés sont les suivants :
| Élément | Rôle |
|---|---|
| Cache de pages Linux | Mécanisme du noyau qui met en cache le contenu des fichiers disque dans la RAM |
splice() | Appel système zero-copy qui relie des données par référence à l’intérieur du noyau sans les copier dans l’espace utilisateur |
AF_ALG | Interface permettant d’utiliser l’API crypto du noyau Linux comme une socket depuis l’espace utilisateur |
| Traitement AEAD in-place | Optimisation qui traite les buffers d’entrée et de sortie dans le même buffer au lieu de les séparer |
authencesn | Template crypto qui génère une écriture scratch de 4 octets pendant le traitement AEAD |
Le flux principal de la vulnérabilité est le suivant :
Fichier lisible
↓
Chargé dans le cache de pages Linux
↓
Référence du cache de pages transmise au chemin crypto AF_ALG via splice()
↓
Le traitement AEAD in-place lie les scatterlists d’entrée et de sortie
↓
Écriture scratch de 4 octets lors du traitement authencesn
↓
L’écriture se produit non pas dans un buffer de sortie séparé, mais dans le cache de pages
↓
Mutation du cache de pages
Autrement dit, splice() transmet une référence au cache de pages, le traitement AEAD in-place lie l’entrée et la sortie sur le même chemin, et authencesn provoque effectivement une écriture de 4 octets.
La structure du dépôt utilisé pour l’exercice est la suivante :
copy-fail-c/
├── exploit.c
├── exploit-passwd.c
├── vulnerable.c
├── payload.c
├── utils.c
├── utils.h
├── Makefile
└── nolibc/
| Fichier | Rôle | Utilisation dans cet exercice |
|---|---|---|
utils.c, utils.h | Implémentation de la primitive de mutation du cache de pages basée sur AF_ALG/splice | Utilisé pour l’analyse et l’exécution de vulnerable |
vulnerable.c | Outil non destructif de vérification de vulnérabilité basé sur un testfile temporaire | Exécuté |
exploit.c | Variante de modification du cache de pages d’un binaire setuid root | Non exécuté |
exploit-passwd.c | Variante de modification du cache de pages de /etc/passwd | Non exécuté |
payload.c | Payload exécuté avec les privilèges root | Non exécuté |
Makefile | Automatisation de la construction | Utilisé uniquement pour la cible vulnerable |
nolibc/ | Code de remplacement de la libc légère pour construire de petits ELF statiques | Analyse uniquement |
utils.cLe cœur de utils.c est la primitive de mutation du cache de pages de la famille patch_chunk(). Cette fonction utilise AF_ALG et splice() pour connecter le cache de pages du fichier cible au chemin de traitement crypto, et vérifie si, sur un noyau vulnérable, une partie du cache de pages est écrasée pendant le traitement AEAD.
vulnerable.cvulnerable.c ne touche à aucun fichier système réel. Il crée un testfile temporaire dans le répertoire courant et vérifie si le cache de pages de ce fichier est altéré.
Dans ce projet, seul ce fichier a été exécuté.
Avant de mettre à jour le noyau, l’état de l’OS, du noyau et des paquets a été enregistré.
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
Dans cet exercice, nous n’avons pas utilisé la construction par défaut make qui compile également les binaires d’exploit ; seule la cible vulnerable a été utilisée.
./vulnerable > ../before/vulnerable-output.txt 2>&1
echo $? >> ../before/vulnerable-output.txt
cat ../before/vulnerable-output.txt
Résultat avant le patch :

Diagnostic :
code de sortie 100
→ Mutation du cache de pages confirmée
→ La primitive Copy Fail fonctionne sur le noyau avant le patch
Après avoir sauvegardé les résultats avant le patch, la mise à jour des paquets Ubuntu a été effectuée.
sudo apt update
sudo apt full-upgrade -y
sudo reboot
Après redémarrage, le noyau est passé à :
Avant : 6.8.0-53-generic
Après : 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
Résultat après le patch :

Comparaison des résultats :
| Élément | Avant le patch | Après le patch |
|---|---|---|
| Noyau | 6.8.0-53-generic | 6.8.0-134-generic |
| Résultat du checker | VULNERABLE | authencesn template not registered |
| Code de sortie | 100 | 2 |
| Mutation du cache de pages | Confirmée | Le checker n’a pas pu atteindre l’étape de mutation |
| Interprétation | La primitive Copy Fail fonctionne | Échec d’entrée dans le chemin AEAD/authencesn requis par le PoC |
exit_code=2 après le patch ne signifie pas simplement “non vulnérable”. Plus précisément :
Le template authencesn(hmac(sha256),cbc(aes)) de AF_ALG n’est pas enregistré,
le checker n’a donc pas pu déterminer directement l’état de vulnérabilité.
Une vérification supplémentaire a montré que le chargement du module algif_aead était bloqué après la mise à jour Ubuntu.
lsmod | grep -E 'af_alg|algif_aead'
Résultat :
af_alg 32768 0
algif_aead n’était pas chargé.
sudo modprobe algif_aead
Résultat :
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
Vérification de la configuration de blocage :
grep -R "algif_aead" /etc/modprobe.d /lib/modprobe.d 2>/dev/null
Résultat :
/etc/modprobe.d/disable-algif_aead.conf:# Disable algif_aead module due to CVE-2026-31431 (AKA copy.fail)
/etc/modprobe.d/disable-algif_aead.conf:install algif_aead /bin/false
Par conséquent, il est plus précis d’interpréter le résultat après le patch comme suit :
Après la mise à jour de sécurité Ubuntu, le noyau est passé à 6.8.0-134-generic,
et une atténuation basée sur kmod bloquant le module algif_aead a été appliquée.
En conséquence, le checker vulnerable de copy-fail-c n’a pas pu
se lier au template AF_ALG authencesn(hmac(sha256),cbc(aes)) requis par le PoC,
et l’étape de mutation du cache de pages n’a pas été atteinte.
Autrement dit, ce qui a été observé dans cet exercice n’est pas seulement l’effet d’un correctif du code du noyau, mais l’application combinée d’une mise à jour du noyau et du blocage du module algif_aead après la mise à jour de sécurité Ubuntu, ce qui a empêché le même chemin PoC de se poursuivre.
Copy Fail peut altérer le cache de pages sans modifier directement le fichier disque, donc une détection basée uniquement sur le hachage des fichiers est limitée. Par conséquent, la détection basée sur le comportement des appels système est importante.
Dans cet exercice, auditd a été utilisé pour observer les appels système suivants :
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)Les logs montrent que le processus vulnerable a créé une socket AF_ALG.
comm=vulnerable
syscall=socket
success=yes
a0=alg
key=copyfail_afalg
bind()Dans l’environnement après le patch/atténuation, le processus vulnerable a tenté de se lier au template authencesn mais a échoué.
comm=vulnerable
syscall=bind
success=no
exit=ENOENT(No such file or directory)
saddr_fam=alg
key=copyfail_bind
Cela signifie que dans l’environnement post-patch, le PoC a pu créer la socket AF_ALG, mais a échoué lors de la liaison au template authencesn(hmac(sha256),cbc(aes)).
splice() / sendmsg()Après le patch, comme l’étape bind() a échoué, le checker n’a pas pu atteindre les étapes splice() et sendmsg(). Par conséquent, aucun flux significatif lié à vulnerable n’a été observé dans les logs de ces appels système.
Dans un environnement opérationnel, pour observer les vulnérabilités de type Copy Fail, on peut surveiller la combinaison des comportements suivants :
| Élément à détecter | Signification |
|---|---|
socket(AF_ALG, ...) | Tentative d’utilisation de l’API crypto du noyau |
bind() avec authencesn | Tentative d’utilisation du template crypto AEAD/authencesn |
splice() | Transmission d’une référence du cache de pages vers un chemin interne du noyau |
sendmsg() / recvmsg() | Exécution d’une requête crypto AF_ALG |
| Exécution d’un binaire setuid | Possibilité de cashout d’élévation de privilèges |
Dans cet exercice, les événements socket(AF_ALG) et l’échec de bind() ont été confirmés via auditd.
La réponse la plus fondamentale est d’appliquer les mises à jour de sécurité de la distribution.
sudo apt update
sudo apt full-upgrade -y
sudo reboot
Dans cet exercice, après la mise à jour, l’environnement est passé à Ubuntu 24.04.4 / noyau 6.8.0-134-generic.
algif_aeadAprès la mise à jour Ubuntu, la configuration suivante a été observée :
/etc/modprobe.d/disable-aligf_aead.conf
install algif_aead /bin/false
Cette configuration empêche le chargement du module algif_aead, bloquant ainsi l’entrée dans le chemin AF_ALG AEAD requis par le PoC.
Dans les applications serveur classiques, l’utilisation directe d’AF_ALG peut être rare. L’appel socket(AF_ALG) peut donc constituer un point de détection.
Les résultats de cet exercice peuvent être résumés comme suit :
Avant le patch :
Ubuntu 24.04.2 / noyau 6.8.0-53-generic
Code de sortie du checker vulnerable : 100
Mutation du cache de pages confirmée
→ La primitive Copy Fail fonctionne
Après le patch :
Ubuntu 24.04.4 / noyau 6.8.0-134-generic
Code de sortie du checker vulnerable : 2
Échec de la liaison au template authencesn
Configuration de blocage du module algif_aead confirmée
→ Le même chemin PoC n’a pas atteint l’étape de mutation du cache de pages
La conclusion de ce projet est donc :
Sur le noyau avant le patch, la primitive de mutation du cache de pages de Copy Fail fonctionnait effectivement.
Ensuite, après application de la mise à jour de sécurité Ubuntu, le noyau est passé à6.8.0-134-generic, et une configuration de blocage du modulealgif_aead(basée surkmod) a été appliquée.
En conséquence, le PoC n’a pas pu se lier au templateauthencesn(hmac(sha256),cbc(aes))de AF_ALG requis, et le même checker n’a pas atteint l’étape de mutation du cache de pages.
Autrement dit, les résultats de cet exercice ne permettent pas d’affirmer que « le correctif du code du noyau lui-même a directement bloqué la mutation du cache de pages », mais ce qui peut être affirmé avec certitude sur la base des logs et résultats observés est que le blocage du module algif_aead après la mise à jour de sécurité Ubuntu a empêché le chemin PoC de se poursuivre.
Avis de sécurité Ubuntu - USN-8226-1 : mise à jour kmod
https://ubuntu.com/security/notices/USN-8226-1
Blog Ubuntu - Correctifs disponibles pour CVE-2026-31431 Copy Fail
https://ubuntu.com/blog/copy-fail-vulnerability-fixes-available
Dépôt PoC copy-fail-c
https://github.com/jihwan77/copy-fail-c
Les points clés confirmés à travers ce projet sont les suivants :
1. Copy Fail est une vulnérabilité du noyau combinant AF_ALG, splice(), AEAD in-place, authencesn et le cache de pages.
2. Avant le patch, dans l’environnement Ubuntu 24.04.2 / noyau 6.8.0-53, le checker non destructif a confirmé une mutation du cache de pages.
3. Après le patch, dans l’environnement Ubuntu 24.04.4 / noyau 6.8.0-134, la liaison authencesn a échoué.
4. Des vérifications supplémentaires ont montré que le chargement du module algif_aead était bloqué par une configuration /bin/false.
5. Les événements socket(AF_ALG) et l’échec de bind() ont pu être observés via auditd.
6. Les réponses opérationnelles peuvent être résumées comme suit : mise à jour du noyau/paquets de sécurité, restriction d’algif_aead, surveillance des appels système AF_ALG, et vérification des binaires setuid.