Ce qui s’est passé
Le 29 avril 2026, la société de sécurité Theori a divulgué publiquement CVE-2026-31431, surnommée Copy Fail — une faille dans le kernel Linux permettant à n’importe quel utilisateur local non-privilégié d’obtenir les droits root de manière déterministe, sans condition de course, sur la quasi-totalité des distributions Linux depuis 2017.
Ce qui rend cette vulnérabilité particulièrement remarquable, c’est sa méthode de découverte : c’est un agent IA baptisé Xint Code (développé par Theori) qui a localisé le bug en moins d’une heure, après qu’un chercheur humain lui a simplement demandé d’explorer les chemins accessibles dans le sous-système crypto du kernel.
La faille n’avait pas été détectée pendant 9 ans malgré des milliers d’yeux humains sur le code.
La vulnérabilité technique
Origine du bug
Copy Fail est née de l’accumulation de trois modifications du kernel sur une décennie :
- 2011 : Ajout de
authencesn, un wrapper AEAD pour IPsec (Extended Sequence Numbers) - 2015 : Introduction du support des sockets AEAD via l’interface
AF_ALG(kernel crypto API accessible depuis l’espace utilisateur) - 2017 : Optimisation « in-place » ajoutée dans
algif_aead.cpour éviter des copies mémoire inutiles
C’est cette optimisation de 2017 qui a introduit le bug. Elle permettait aux pages du page cache d’un fichier de se retrouver dans la scatterlist de destination d’une opération AEAD. En d’autres termes, le kernel pouvait écrire dans la mémoire mappée d’un fichier en pensant écrire dans un buffer temporaire.
Le mécanisme précis
Au cœur du problème, authencesn utilise le buffer de destination de l’appelant comme espace de travail temporaire pour réorganiser les octets ESN (Extended Sequence Number). Il écrit 4 octets à l’offset assoclen + cryptlen — potentiellement en dehors des limites du buffer, dans des pages du page cache chaînées via sg_chain().
Résultat : une écriture de 4 octets contrôlés dans le page cache de n’importe quel fichier lisible par l’utilisateur, sans toucher le disque.
Le patch officiel (commit a664bf3d603d) revient simplement sur l’optimisation de 2017.
Distributions et kernels affectés
Toutes les distributions utilisant un kernel ≥ 2017 avec l’interface AF_ALG activée (configuration par défaut).
Les tests officiels confirment une exploitation réussie sur :
| Distribution | Version testée |
|---|---|
| Ubuntu 24.04 LTS | kernel 6.17.0-1007-aws |
| Amazon Linux 2023 | kernel 6.18.8-9.213.amzn2023 |
| RHEL 10.1 | kernel 6.12.0-124.45.1.el10_1 |
| SUSE 16 | kernel 6.12.0-160000.9-default |
| Rocky Linux 9.7 | — |
Résistances naturelles :
- Les systèmes avec SELinux en mode enforcing (RHEL/CentOS/Fedora avec configuration stricte) résistent à l’exploitation par défaut
- Les environnements avec des profils seccomp bloquant
AF_ALGne sont pas exploitables
Contextes particulièrement exposés :
- Serveurs mutualisés et hébergements partagés
- Clusters Kubernetes / nœuds worker
- Fermes CI/CD (GitHub Actions self-hosted, GitLab runners, Jenkins)
- Environnements cloud et SaaS multi-tenant
Désactiver la faille sans attendre les patches distro
Le module vulnérable est algif_aead, chargé à la demande lors de l’utilisation de l’interface AF_ALG avec un algorithme AEAD. Il suffit de l’interdire.
Méthode 1 — Blacklist immédiate (persistante après reboot)
echo "install algif_aead /bin/false" > /etc/modprobe.d/disable-algif-aead.conf
Si le module est déjà chargé en mémoire, le décharger :
rmmod algif_aead 2>/dev/null || true
Vérifier qu’il n’est plus chargé :
lsmod | grep algif_aead
# doit retourner vide
Méthode 2 — Bloquer via seccomp (conteneurs / workloads non fiables)
Pour les environnements conteneurisés, bloquer la création de sockets AF_ALG via un profil seccomp est une mitigation plus large, recommandée indépendamment du patch :
{
"syscalls": [
{
"names": ["socket"],
"action": "SCMP_ACT_ALLOW",
"args": [
{ "index": 0, "value": 38, "op": "SCMP_CMP_NE" }
]
}
]
}
(La valeur 38 correspond à AF_ALG sur x86_64)
Ce que vous ne cassez PAS en désactivant algif_aead
L’impact opérationnel est quasi nul pour la grande majorité des systèmes. algif_aead n’est pas utilisé par :
- dm-crypt / LUKS (chiffrement de disque)
- kTLS (TLS kernel-space)
- IPsec en configuration standard
- OpenSSL par défaut
- SSH (OpenSSH n’utilise pas l’interface AF_ALG)
Il est uniquement utilisé par les applications appelant explicitement l’engine afalg d’OpenSSL — cas rare hors benchmarking ou systèmes embarqués.
Comment fonctionne l’exploit
Ce chapitre décrit la mécanique de l’exploit tel que divulgué publiquement sur copy.fail. L’objectif est de comprendre ce qui se passe pour mieux défendre.
Vue d’ensemble
L’exploit est un script Python de 732 octets n’utilisant que la stdlib standard (os, socket, zlib). Il fonctionne de manière 100 % déterministe — pas de timing, pas de brute-force, pas de condition de course.
La cible par défaut est /usr/bin/su, un binaire setuid root lisible par tous les utilisateurs.
La chaîne en 6 étapes
1. Ouverture d’un socket AF_ALG sans privilèges
sock = socket.socket(socket.AF_ALG, socket.SOCK_SEQPACKET, 0)
sock.bind(("aead", 0, 0, "authencesn(hmac(sha256),cbc(aes))"))
N’importe quel utilisateur peut ouvrir un socket AF_ALG. C’est une feature intentionnelle du kernel pour donner accès aux accélérateurs crypto matériels depuis l’espace utilisateur.
2. Injection du page cache de /usr/bin/su via splice()
splice() déplace des données entre un fd et un pipe sans copie mémoire — directement via les pages du page cache. L’exploit splice les pages de /usr/bin/su (lisible par tous) dans la scatterlist de destination de l’opération AEAD.
3. Construction de l’AAD malveillant
Les octets 4-7 de l’AAD (Additional Authenticated Data) passé via sendmsg() contiennent les 4 octets à écrire. Le kernel les traitera comme le seqno_lo de l’ESN.
4. Déclenchement de l’écriture hors-limites
recv() déclenche l’opération de déchiffrement AEAD. À l’intérieur d’authencesn, le kernel extrait seqno_lo de l’AAD et l’écrit à dst[assoclen + cryptlen] — qui pointe désormais, grâce au splice(), dans une page du page cache de /usr/bin/su.
5. Injection du shellcode par blocs de 4 octets
Un shellcode de 160 octets est injecté par itérations successives (un cycle sendmsg + splice + recv par bloc de 4 octets), ciblant l’entrypoint du binaire en mémoire.
6. Exécution
Le binaire corrompu en mémoire (le page cache — le fichier physique sur disque reste intact) s’exécute avec les privilèges setuid root. Shell root obtenu.
Pourquoi c’est pire que Dirty Cow et Dirty Pipe
| Dirty Cow (2016) | Dirty Pipe (2022) | Copy Fail (2026) | |
|---|---|---|---|
| Race condition | Oui (fragile) | Non | Non |
| Kernels affectés | Variable | ≥ 5.8 | ≥ 2017 |
| Taille exploit | ~100 lignes C | ~70 lignes C | 732 octets Python |
| Dépendances | Aucune | Aucune | Python 3.10+ stdlib |
| Fiabilité | ~80% | ~95% | 100% |
Copy Fail est déterministe et portable : le même script non modifié fonctionne sur Ubuntu, RHEL, SUSE et Amazon Linux sans aucune adaptation.
Timeline de divulgation
| Date | Événement |
|---|---|
| 23 mars 2026 | Rapport envoyé à l’équipe sécurité du kernel Linux |
| 25 mars 2026 | Patch proposé et reviewé |
| 1er avril 2026 | Commit a664bf3d603d fusionné dans mainline |
| 22 avril 2026 | CVE-2026-31431 assigné |
| 29 avril 2026 | Divulgation publique + publication du PoC |
Ce qu’il faut faire maintenant
Priorité 1 — Mitigation immédiate (5 minutes)
echo "install algif_aead /bin/false" > /etc/modprobe.d/disable-algif-aead.conf
rmmod algif_aead 2>/dev/null || true
Priorité 2 — Patcher le kernel
Les patches sont disponibles dans mainline depuis le 1er avril 2026. La plupart des distributions majeures ont publié des kernels corrigés dans les jours suivant la divulgation du 29 avril. Mettre à jour dès que le package est disponible :
# Debian / Ubuntu
apt update && apt upgrade linux-image-generic
# RHEL / Rocky / AlmaLinux
dnf update kernel
# SUSE
zypper update kernel-default
# Amazon Linux
yum update kernel
Priorité 3 — Vérifier les environnements conteneurisés
Même sur un host patché, ajouter un profil seccomp bloquant AF_ALG sur les workloads qui n’en ont pas besoin est une bonne pratique de défense en profondeur.
Sources : copy.fail (divulgation officielle Theori/Xint), Help Net Security, The Register, Hacker News