
CVE-2026-98432 : un simple serveur TCP IPv4 est vulnérable, MPTCP n'est pas le déclencheur. Déclenchement du bug, preuves et analyse.
Écrit par DeepSeek.
Un simple serveur TCP IPv4 est vulnérable. MPTCP n'est pas le déclencheur.
Nous avons compilé Linux 6.18.55 à partir de l'archive de version et fait lire au noyau de la mémoire libérée sur un listener IPPROTO_TCP normal. KASAN l'a signalé deux fois. Aucun socket MPTCP n'a jamais été créé, et une exécution avait MPTCP désactivé dans le noyau.
Le même bug fait que le noyau copie des octets depuis un objet libéré dans la réponse qu'il renvoie. C'est la primitive dont a besoin une attaque KASLR, et nous l'avons observée se produire dans des travaux non publiés. Nous n'avons pas construit de fuite d'adresse noyau, et nous n'avons pas prouvé d'écriture.
Ce qui est prouvé ici, avec code et journaux : l'use-after-free est réel, le TCP standard l'atteint, et le correctif amont l'arrête.
| Noyau | MPTCP | Tentatives | Temps | Résultat |
|---|---|---|---|---|
| 6.18.55, sans correctif | non utilisé | 134 955 | 34 s | use-after-free KASAN |
| 6.18.55, sans correctif | désactivé | 191 431 | 80 s | use-after-free KASAN |
| 6.18.55 + correctif | non utilisé | 439 316 | 411 s | propre |
Très difficile. Avec KASAN, le lecteur est lent, donc le bug apparaît en quelques centaines de milliers de tentatives. Sur un noyau normal, il est bien plus rare : sur environ 48 millions de tentatives, nous avons vu deux événements, tous deux dans les mêmes cinq secondes.
C'est trop peu pour énoncer un taux. Le maximum que nous affirmerons est une borne d'environ 1e-7 par tentative, et même cela est un meilleur cas, car notre harnais force les deux paquets sur deux CPU et une vraie carte réseau envoie généralement un flux vers un seul CPU.
Ainsi, une exécution propre ne signifie pas un noyau sûr. Lisez les sections 5.2 et 6 de ANALYSIS.md avant de citer un quelconque chiffre.
Un serveur TCP reçoit un SYN. Le SYN porte une option IPv4 (Record Route ou Timestamp). Le noyau enregistre ces options sur le socket de requête.
Un second SYN pour la même connexion arrive. Le noyau construit un SYNACK pour celui-ci et lit les options enregistrées.
Au même moment, le handshake se termine. Le socket enfant reçoit le même pointeur, pas une copie. Le serveur ferme l'enfant, et le noyau libère les options avec un simple kfree().
Le code du SYNACK lit encore cette mémoire. C'est l'use-after-free. La même lecture est ce qui place des octets libérés dans le paquet.
C'est un déclencheur de bug, pas un exploit. Il ne fuit pas d'adresses noyau, n'écrit pas en mémoire noyau et n'obtient pas root. Il montre le noyau lisant de la mémoire libérée ; KASAN est le juge.
Le dépôt s'arrête là volontairement. Les étapes ultérieures ont été travaillées en privé et ne sont pas publiées ici.
scripts/get-kernel.sh # fetch 6.18.55, sha256 checked, into linux/
scripts/build-kernel.sh vuln # KASAN kernel, no fix
scripts/build-kernel.sh patched # KASAN kernel, with the fix
scripts/build-harness.sh # builds harness/init + initramfs
scripts/run.sh vuln 90 selftest # checks the wiring only
scripts/run.sh vuln 600 # expect a KASAN report
scripts/run.sh patched 600 # expect nothing
Vous avez besoin de gcc, make, bison, flex, bc et qemu-system-x86_64. KVM aide beaucoup.
La VM prend 2 Go de RAM et 8 vCPU.
Une seule exécution peut ne rien montrer. Ce n'est pas une preuve qu'un noyau est sûr. Exécutez-la
plusieurs fois, et lisez les mises en garde dans ANALYSIS.md.
Ne faites pas confiance à la chaîne de version. Regardez le code dans le binaire.
scripts/check-free-sites.py
Il trouve les deux sites libres dans le noyau en cours d'exécution et indique quelle fonction ils appellent : kfree (défectueux) ou kvfree_call_rcu (corrigé).
Sur la machine sur laquelle ceci a été écrit (6.18.59_1), les deux sites utilisent
kvfree_call_rcu, donc ce noyau est corrigé.
Un hôte est exposé si les trois conditions suivantes sont réunies :
L'attaquant contrôle le point 2. La plupart des serveurs internet sont donc exposés, et « nous n'utilisons pas MPTCP » n'aide pas.
Deux remarques :
accept_source_route=0 ne vous protège pas. Cela ne bloque que le routage à la source, pas l'option Record Route ni Timestamp.| Chemin | Contenu |
|---|---|
ANALYSIS.md | le rapport complet : chemin source, méthode, résultats, limites |
harness/ | le déclencheur du bug qui s'exécute comme /init dans QEMU |
patches/ | le correctif amont, utilisé pour la compilation de contrôle |
scripts/ | assistants de récupération, compilation, exécution et vérification |
evidence/ | rapports KASAN, journaux d'exécution, comparaison des compilations |
Uniquement des noyaux de test, et seulement ceux qui vous appartiennent. Rien ici ne doit être dirigé vers des systèmes que vous ne contrôlez pas.
MIT pour notre code et notre texte. patches/ contient un commit du noyau Linux et reste sous GPL-2.0. Voir LICENSE.