En bref
Aller directement à la version longue ↓
Description : « Bad Epoll », référencé sous le numéro CVE-2026-46242, est une vulnérabilité de type « use-after-free » liée à une condition de concurrence dans le sous-système epoll du noyau Linux. Dans la branche de nettoyage de la fonction ep_remove(), une branche de fermeture efface le lien epoll du fichier et continue de l’utiliser, tandis qu’une libération simultanée du fichier, détectant ce lien effacé, libère l’objet sous-jacent. Un utilisateur non privilégié exploite cette écriture erronée pour accéder à la racine.
Impact : un utilisateur local sans privilèges remporte la course, transforme l'écriture de 8 octets de type « use-after-free » en prise de contrôle d'une structure « file » via une attaque « cross-cache », puis passe à une lecture arbitraire du noyau et au détournement du flux de contrôle – droits root complets. Le PoC public (J-jaeyoung/bad-epoll, soumis au Google kernelCTF) fait état d’une fiabilité de 99 % sur un noyau 6.12, la même base que celle d’AlmaLinux 10.
Statut : Le bogue est avéré et a déjà été corrigé en amont. Il a été signalé en privé en février, corrigé le 24 avril, puis rendu public le 30 mai – la correction a précédé la divulgation de cinq semaines, et il n'y a eu aucune exploitation en milieu réel. À l'origine, il s'agissait d'un « 0-day » du kernelCTF, mais pour les défenseurs aujourd'hui, il s'agit d'un « N-day » avec un exploit public.
Gravité : kernel.org et le NVD lui attribuent un score CVSS de 7,8 (High) (AV : L / AC : L / PR : L) ; Red Hat lui attribue un score de 7,0, considérant que la condition de concurrence (race condition) d’environ 6 instructions est difficile à exploiter. Dans tous les cas, l’exploit permet d’obtenir les privilèges root, et la fiabilité d’environ 99 % du PoC fait de cette fenêtre d’exploitation très étroite un problème concret, et non théorique.
Pourquoi est-ce important ? Les systèmes exposés sont ceux où l'isolation locale est le résultat : hébergements mutualisés, serveurs multi-locataires, environnements d'intégration continue (CI) et nœuds de conteneurs exécutant du code non fiable. epoll est à la base de presque tous les services ; il n'y a donc aucune surface d'attaque à désactiver. Une exploitation de l'exécution locale (LPE) constitue ici l'événement permettant de franchir la frontière de sécurité.
Agissez immédiatement : il n'existe aucune mesure de mitigation par la configuration — epoll ne peut pas être désactivé. Isolez toute exécution locale non fiable et vérifiez que le correctif est bien intégré au noyau, plutôt que de vous fier à l'échec d'une tentative d'exploitation. Un correctif « sans redémarrage » de KernelCare est en cours d'analyse ; rien n'est encore disponible dans les dépôts. Détails ci-dessous.
Vous en avez assez de devoir programmer un nouveau redémarrage d'urgence ?
KernelCare applique les correctifs du noyau Linux sans temps d'arrêt, sans perturbation et sans nécessiter de fenêtres de maintenance d'urgence.
État de KernelCare (mis à jour le 04/07/2026 — en cours d'analyse) : Il s'agit d'une lignée de noyaux commune : RHEL, AlmaLinux, Rocky, Oracle Linux et CloudLinux de la même version majeure partagent le même ep_remove() code et exposition — considérer « EL10 » et « EL9 » comme une seule et même famille. Red Hat indique que RHEL 9 et 10 sont affectées (7/8 ne sont pas affectées). EL10 est affectée ; EL9 hérite très probablement du commit d’introduction rétroporté. Nous sommes encore en train de vérifier la reproductibilité et les versions exactes concernées. Aucun correctif KernelCare n’a encore fait l’objet d’une validation complète, et aucun n’est encore disponible dans un flux (suivi sous la référence KCARE-27500). Il n’existe à ce jour aucune configuration permettant au client d’atténuer le risque — voir la section « Mesures d’atténuation ».
La version longue
Deux raisons pourraient vous inciter à clore ce ticket prématurément, mais elles sont toutes les deux erronées.
Le premier est le fichier README du PoC lui-même, qui précise que le bug n’affecte que les noyaux « basés sur la version 6.4 ou plus récente » et considère que les noyaux basés sur la version 6.1 sont sûrs. Si vous lisez cela sur une machine CloudLinux 9 (basée sur la version 5.14), vous pourriez raisonnablement en conclure que vous n’êtes pas concerné. Vous auriez tort. Le deuxième élément est l’exécution d’un exploit sans incident. Dirigez le PoC public vers un noyau sur une petite machine virtuelle, observez-le perdre la course quelques centaines de milliers de fois, et il est facile d’écrire « non reproductible, non affecté » et de passer à autre chose. C’est également faux, et dans le cas de ce bug, cela peut s’avérer dangereux.
« Bad Epoll » est une condition de concurrence de type « use-after-free » dans le sous-système eventpoll du noyau – le mécanisme qui sous-tend les appels système epoll dont dépendent pratiquement tous les services réseau de la machine. La condition de concurrence se situe dans la branche de nettoyage de la fonction ep_remove(), et la fenêtre d’exploitation correspond à environ six instructions CPU. Si l’on rate cette fenêtre, il ne se passe rien. Si vous la réussissez, comme le fait l’exploit public avec une grande fiabilité sur un noyau 6.12, un utilisateur sans privilèges se retrouve alors en passe d’obtenir les droits root.
Il est confirmé que la vulnérabilité EL10 est exploitable et qu’EL9 est très probablement affectée par le commit d’introduction rétroporté ; il ne s’agit donc pas d’une interprétation prudente d’un avis de fournisseur. Il s’agit d’un véritable bug, pour lequel un correctif a été fourni en amont, et dont un exploit public déjà transformé en arme figure dans une soumission au kernelCTF.
Comment fonctionne le mauvais Epoll ?
epoll conserve un struct eventpoll objet, soutenu par un struct file, pour chaque instance epoll. Il est important de procéder à cette suppression de manière propre, car deux processus peuvent finir par fermer le même élément presque simultanément : le processus de suppression epoll et une libération simultanée du fichier sous-jacent.
Le bug est une petite erreur d'ordre dans cette séquence de démontage. À l'intérieur de la fonction ep_remove(), l'ancien code effaçait l'association epoll du fichier (file->f_ep) tout en tenant file->f_lock, puis a continué à utiliser ce même fichier et ses données eventpoll à l'intérieur de la section critique. Un processus concurrent __fput() Si l'on emprunte la voie rapide de libération pendant cette fenêtre, on observe la valeur NULL transitoire f_ep, conclut qu'il n'a pas de nettoyage epoll à effectuer, et passe directement à f_op->release. Dans un schéma « epoll-surveille-epoll », ce chemin libère l'élément surveillé struct eventpoll sans équivoque. Le premier chemin est toujours en cours d'exécution, et son prochain hlist_del_rcu() écrit via un pointeur intégré dans de la mémoire qui vient d'être libérée.
[Unprivileged local process]
│ creates linked epoll objects backed by struct file
▼
[Two close paths race inside ep_remove()]
│ path A clears file->f_ep, keeps using the file
│ path B (__fput) sees NULL f_ep, skips epoll cleanup
▼
[Path B frees the watched struct eventpoll / recycles the file slot]
│ path A's hlist_del_rcu() writes into freed memory
▼
[Attacker-controlled 8-byte use-after-free write]
▼
[Cross-cache reclaim gives control of a struct file]
▼
[Arbitrary kernel read + control-flow hijack]
▼
[uid=0 root shell]
L'écriture proprement dite porte sur huit octets de mémoire libérée, ce qui semble gérable jusqu'à ce que l'on observe ce que l'exploit en fait. La chaîne publique utilise quatre objets epoll répartis en deux paires : la fermeture d'une paire déclenche la condition de concurrence, tandis que l'autre devient la victime. Cela transforme l'écriture de 8 octets en une utilisation après libération (use-after-free) sur un struct file, utilise la récupération de mémoire entre caches pour remplacer cet emplacement par un objet contrôlé par l'attaquant, puis parvient à lire arbitrairement le noyau et à détourner le flux de contrôle.
C'est précisément en raison de la faible marge de la course que cette faille est facile à sous-estimer – et qu'elle est passée inaperçue pendant des années. Le même commit de 2023 qui l'a introduite a également introduit une faille de type « race condition » apparentée, CVE-2026-43074, qui a été détectée et corrigée plus tôt en 2026. Cette correction n'a pas résolu le problème « Bad Epoll ». Le fait d'appliquer une correction epoll cette année ne prouve pas que vous soyez concerné par les deux failles.
Ce que modifie le correctif « Upstream »
Le correctif est court et autonome, ce qui explique pourquoi il se porte sans problème. Il empêche la fonction ep_remove() d'utiliser une référence non protégée au fichier qu'elle est en train de supprimer.
Le chemin corrigé place le fichier en tête, en prenant une référence via epi_fget() et tenant un struct file *file __free(fput) bloquer avant qu'il ne touche file->f_lock. Tant que cette référence est conservée, le compteur de références du fichier ne peut pas tomber à zéro, donc __fput() ne peut pas démarrer et le chemin de libération concurrent ne peut pas libérer le fichier ou son objet eventpoll de la procédure de nettoyage. Si le verrou ne peut pas être acquis, ep_remove() s'interrompt avant d'effectuer le nettoyage f_ep, et le chemin de libération suit la procédure normale de nettoyage, plus lente, qui se synchronise via le mutex eventpoll au lieu d'entrer en concurrence.
D'un point de vue conceptuel :
Before: clear epoll link → keep using file → concurrent release frees it → write into freed memory
After: pin file reference → do cleanup while pinned → concurrent release cannot free → release reference
Cette seule modification résout les deux aspects du bug : la libération de la mémoire surveillée struct eventpoll, ainsi que le recyclage du struct file emplacement alors que le chemin d'origine considère toujours qu'il détient un verrou valide.
Qui est concerné ?
En bref, pour la famille CloudLinux et AlmaLinux : les versions 9 et 10 sont concernées et cela a été confirmé ; la version 8 ne devrait pas l'être.
Personnes concernées:
- CloudLinux 10 / AlmaLinux 10 (basé sur la version 6.12) : une variante du PoC public, qui provoque uniquement un plantage, fait basculer de manière fiable en mode panique un hôte AlmaLinux 10 sans privilèges sur un serveur physique en quelques secondes – il s’agit d’une faille « use-after-free » exploitable et weaponisée, et non d’une simple curiosité de laboratoire. Il s’agit de la même base 6.12 que celle sur laquelle l’exploit complet permet d’obtenir les droits root avec une fiabilité de 99 % en amont.
- CloudLinux 9 / AlmaLinux 9 (basées sur la version 5.14) : probablement concernées via le commit d'introduction rétroporté – Red Hat classe RHEL 9 parmi les versions concernées, car le commit d'introduction a été rétroporté dans cette branche. La reproduction du problème sur la branche 5.14 est encore en cours de vérification ; il convient donc de considérer ces versions comme concernées en attendant confirmation, plutôt que comme un fait avéré en interne.
Cela ne devrait pas poser de problème, mais vérifiez avant de vous y fier :
- CloudLinux 8 / AlmaLinux 8 (basé sur la version 4.18) : Red Hat indique que RHEL 7 et 8 ne sont pas concernés, et CL8 devrait donc être exempté par extension. Si un auditeur ou un client a besoin d'une confirmation formelle, vérifiez la source plutôt que de l'affirmer.
La fenêtre de version constitue le premier piège. Le fichier README du PoC décrit une plage de versions « mainline » allant de la v6.4 à celles plus récentes, et qualifie les noyaux basés sur la v6.1 de « sûrs ». Cela est vrai pour la branche « mainline », mais sans intérêt pour Enterprise Linux, car les éditeurs rétroportent la modification en question vers des branches bien plus anciennes. Un noyau EL9 basé sur la version 5.14 se situe bien en dessous de la v6.4 et reste donc concerné. Ne tirez pas de conclusions concernant votre machine EL à partir de la version en amont.
Un échec de reproduction constitue le deuxième piège. Les exploits de type « race condition » sont extrêmement sensibles au nombre de cœurs, à la planification, à la disposition du tas et à la configuration de compilation. Un premier test effectué sur une petite machine virtuelle à deux vCPU n’a révélé aucune « race condition » et semblait correct ; en revanche, un test de reproduction plus poussé sur un serveur physique multicœur a provoqué une panique au niveau de la même ligne du noyau en quelques secondes. Le problème venait d’un environnement de test inadéquat, et non d’un noyau patché. Ne considérez pas l’absence de « race condition » comme un gage de sécurité.
Vérifiez donc par rapport au code source, et non par rapport à l'exploit. Rechercher le hachage du commit en amont à l'aide de `grep` peut induire en erreur, car les backports suppriment ce hachage. Vérifiez plutôt la présence du motif de correction à l'intérieur de la fonction `ep_remove()` :
grep -n 'epi_fget\|__free(fput)' /usr/src/kernels/$(uname -r)/fs/eventpoll.c
Si la fonction ep_remove() verrouille le fichier avec epi_fget() et un __free(fput) Prendre des précautions avant de toucher file->f_lock, le correctif est présent. S'ils sont absents, cela signifie que le noyau n'a pas été corrigé, et que toute exploitation négative exécutée sur celui-ci était un faux négatif.
Agir dès maintenant
Disons-le clairement : il n'existe aucune solution de configuration simple pour remédier à ce problème.
epoll fait partie intégrante de l'interface des appels système. nginx, php-fpm, mysqld, systemd… Presque tous les composants d'un serveur de production s'appuient sur cette interface, qui est activée sur tous les noyaux à usage général. Il n’y a aucun paramètre sysctl à modifier, aucun module à mettre sur liste noire, ni aucune capacité à supprimer qui permette de fermer la brèche de sécurité sans perturber les charges de travail qui font tourner le serveur. Cela ne nécessite même pas d’espaces de noms utilisateur ni de capacités spéciales ; le chercheur note qu’il est accessible depuis des contextes restreints, y compris le bac à sable d’un moteur de rendu de navigateur. Quiconque vous propose une solution de renforcement de la sécurité d’epoll en une seule ligne vous vend un système défaillant.
Comme le bug est uniquement local (AV:L, PR:L), les mesures de sécurité efficaces sont celles que vous connaissez déjà et qui sont un peu ennuyeuses :
- Limitez le nombre de personnes autorisées à exécuter du code sur les hôtes concernés, car ce bug nécessite un point d'ancrage local sans privilèges ; moins il y a de points d'ancrage, moins le risque d'exposition est important.
- Isolez les exécutions locales non fiables et semi-fiables (code client, tâches CI, étapes de compilation) des hôtes que vous devez protéger en priorité, ou placez-les sur des noyaux que vous pouvez corriger en premier.
- Donnez la priorité aux hôtes pour lesquels l'isolation locale constitue la véritable frontière de sécurité : hébergement mutualisé, nœuds multi-locataires, exécuteurs CI, hôtes de conteneurs.
- Vérifiez que le noyau intègre bien le correctif à l'aide de la vérification du code source décrite ci-dessus, plutôt que de conclure à l'absence de risque sur la base d'une exécution silencieuse de l'exploit.
Prise de décision. Si un hôte n'exécute aucun code local non fiable et ne compte qu'un petit nombre d'utilisateurs de confiance, le risque résiduel est moindre et vous pouvez appliquer les correctifs selon votre rythme habituel dès la publication d'une errata ou d'un correctif ne nécessitant pas de redémarrage. Si un hôte exécute du code que vous ne contrôlez pas (hébergement mutualisé, CI, environnement multi-locataires), considérez-le comme exposé dès aujourd'hui et faites passer en priorité un correctif ne nécessitant pas de redémarrage ou un noyau corrigé dès qu'il est disponible.
Patching sans redémarrage
C'est précisément pour ce genre de bogue qu'existent les correctifs sans redémarrage. La modification en amont est disponible, mais cela ne protège pas un système en cours d'exécution : le fournisseur doit la rétroporter, vous devez installer le paquet, et la machine doit démarrer avec le nouveau noyau. C'est lors de cette dernière étape que la vulnérabilité persiste, et c'est justement là où c'est le plus difficile que cela compte le plus.
Ce correctif consiste en une petite modification autonome visant à assainir le code, ce qui en fait un bon candidat pour un correctif applicable sans redémarrage. Il s'agit d'un simple portage en amont de la broche de référence `ep_remove()`, appliquée au noyau en cours d'exécution afin que le nettoyage en cours ne puisse plus libérer le fichier sous-jacent – la même garantie que le correctif en amont, fournie sans redémarrage.
Pour CloudLinux et AlmaLinux, le correctif a été identifié : il s'agit d'un simple backport de la broche de référence ep_remove() issue de la version en amont (backport RHEL 10, Gerrit 257974). Le backport KernelCare est toujours en cours d’analyse, la reproductibilité sous EL10 et EL9 étant en cours de vérification ; aucun correctif n’a donc encore fait l’objet d’une validation complète et aucun n’est pour l’instant disponible dans les branches testing, main ou ePortal. LibCare n’entre pas dans le cadre de cette analyse : il s’agit d’un bogue affectant uniquement le noyau, il n’y a donc pas de bibliothèque de l’espace utilisateur à corriger.
Une fois qu'une version est disponible, son déploiement à partir du canal de test (feed) se déroule comme suit :
kcarectl --update --prefix test
Pour vérifier que la version du patch en cours d'exécution date de la date de publication ou d'une date postérieure :
kcarectl --info | grep kpatch-build-time
La date de compilation à elle seule ne prouve rien. Vérifiez directement la correspondance CVE, l'erratum du fournisseur, le modèle source ou l'état du correctif KernelCare.
Détection
Une utilisation incorrecte d'epoll ne laisse aucune trace identifiable sur le disque. L'exploit fonctionne entièrement dans la mémoire du noyau – en remportant une course, en corrompant un objet libéré, en réécrivant le flux de contrôle – de sorte que les outils de vérification de l'intégrité des fichiers ne peuvent rien détecter. Le déclencheur est construit à partir d'interfaces courantes (création d'instances epoll, enregistrement de descripteurs, timerfds, fermeture de ceux-ci) qui sont normales sur n'importe quel hôte Linux. Cela repousse la détection vers le domaine comportemental, et chacun des éléments suivants constitue un indice, et non une preuve :
- Des processus sans privilèges créent et suppriment un grand nombre d'instances epoll et de timerfds dans des boucles serrées, ce qui revient à exploiter une situation de concurrence étroite de manière intensive.
- Erreurs « oops » du noyau ou bogues liés à la corruption de listes dans la chaîne de nettoyage de `eventpoll`, avec des signatures du type
ep_show_fdinfo,ep_clear_and_put,ep_eventpoll_releaseou__fput. - Des « kernel panics » et des redémarrages à répétition sur un hôte multicœur, sans qu’aucun changement matériel ou de configuration ne vienne les expliquer – un déclencheur « crash-only » provoque un « kernel panic » en quelques secondes.
- Un utilisateur local ou un compte de service obtenant des privilèges peu après une rafale des événements susmentionnés, sans qu'aucun événement « sudo » ou de connexion correspondant ne soit enregistré.
Si du code local non fiable ou partiellement fiable s'est exécuté sur un hôte EL9 ou EL10 exposé et que vous constatez une instabilité du noyau concentrée dans la chaîne de fermeture epoll, donnez la priorité à l'application des correctifs et considérez que cet hôte mérite un examen plus approfondi (nouveaux comptes ou clés SSH, configuration d'authentification modifiée, services inattendus), plutôt que de considérer des hachages de fichiers intacts comme la preuve qu'il n'y a pas eu de compromission.
Pourquoi celui-ci est important
Une faille Epoll ne permet pas l'exécution de code à distance. Personne ne peut pirater votre serveur depuis Internet grâce à cela. Pour les environnements réellement concernés, c'est une maigre consolation.
L'hébergement mutualisé exécute le code des clients. Les runners d'intégration continue (CI) exécutent tout ce que leur a demandé la dernière pull request. Les conteneurs et les nœuds Kubernetes exécutent des charges de travail à différents niveaux de confiance, et les hôtes multi-locataires existent précisément pour isoler les locataires les uns des autres. Dans chacun de ces cas, l’escalade locale des privilèges est l’événement que l’architecture tout entière est censée empêcher. Elle transforme un code autorisé à s’exécuter en un code s’exécutant en tant que root, là où il n’aurait jamais dû l’être. Le fait que ce bug soit également accessible depuis des endroits où la plupart des bugs du noyau ne le sont pas, comme le bac à sable d’un moteur de rendu de navigateur, ne fait qu’élargir la surface d’attaque.
La raison pour laquelle il est facile de se tromper est la même que celle pour laquelle cela est dangereux. Trois signaux plausibles indiquent tous que la situation est « sûre » et induisent tous en erreur : la mention de version « v6.4+ » ne tient pas compte des rétroportages vers EL9 basé sur la version 5.14, l’échec d’une tentative d’exploitation ne reflète pas la difficulté de déclencher une condition de concurrence en six instructions sans effort, et le fait d’avoir appliqué le correctif epoll correspondant plus tôt cette année n’a aucune incidence sur celui-ci. Si vous vous fiez à l’un d’entre eux, vous classerez un hôte vulnérable comme « sûr ».
Le risque se concentre là où il se concentre toujours : les serveurs en retard de quelques mises à jour, les machines de CI qui tournent en continu et que personne ne redémarre, les hébergeurs multi-locataires où la fenêtre de maintenance fait l’objet d’une négociation. Ce sont précisément ces serveurs sur lesquels une faille « N-day » accompagnée d’un PoC public se transforme discrètement en un problème à régler le jour même – et ceux sur lesquels un correctif sans redémarrage fait la différence entre une correction aujourd’hui et une correction au trimestre prochain.
Liste de contrôle des mesures correctives prioritaires
- Considérez CloudLinux 9 et CloudLinux 10 comme concernés et confirmés. N'excluez pas CL9 en vous basant sur la mention « v6.4+ » : le commit d'introduction a été rétroporté dans la branche 5.14.
- Vérifiez chaque noyau en vous basant sur son code source, et non sur le résultat de l'exploitation : vérifiez la fonction ep_remove() pour le
epi_fget()+__free(fput)définir une méthode standard et considérer un test de concept (PoC) ayant échoué comme non concluant. - Ne partez pas du principe que le fait d’avoir « corrigé un bug epoll cette année » résout ce problème ; le correctif associé à CVE-2026-43074 ne résout pas le problème « Bad Epoll ».
- Donnez la priorité aux hôtes pour lesquels l'isolation locale constitue la frontière de sécurité : hébergements mutualisés, nœuds multi-locataires, environnements d'exécution CI, conteneurs et hôtes de développement exécutant du code non fiable.
- Limitez et isolez toute exécution locale non fiable jusqu'à ce qu'un correctif soit mis en place. Il n'existe aucune mesure d'atténuation au niveau de la configuration sur laquelle s'appuyer : epoll ne peut pas être désactivé.
- Vérifiez CloudLinux 8 à la source avant d'affirmer à qui que ce soit qu'il ne présente aucun risque.
- Recherchez les « kernel panics » inexpliqués et toute activité inhabituelle liée à epoll/timerfd dans la chaîne de démontage d'eventpoll, et ne considérez pas les hachages de fichiers intacts comme des preuves suffisantes.
- Appliquez le correctif KernelCare sans redémarrage dès qu'il aura été validé et intégré au flux de mises à jour, en particulier sur les serveurs les plus difficiles à redémarrer. Le correctif est encore en cours d'analyse ; les balises K seront publiées ici dès que les versions seront disponibles.
Appliquez des correctifs à tous les noyaux, sans redémarrage. Si vous n'utilisez pas encore KernelCare, c'est le moment idéal pour découvrir comment l'application de correctifs sans redémarrage protège les systèmes Linux critiques, sans nécessiter de fenêtres de maintenance d'urgence ni de temps d'arrêt.
Procurez-vous KernelCare dès aujourd’hui →
Références
- Red Hat CVE-2026-46242 – https://access.redhat.com/security/cve/cve-2026-46242
- NVD CVE-2026-46242 (kernel.org CNA, CVSS 3.1 7,8) – https://nvd.nist.gov/vuln/detail/CVE-2026-46242
- linux-cve-announce – https://lore.kernel.org/linux-cve-announce/
- Démonstration publique de faisabilité (PoC) et analyse des causes profondes (Jaeyoung Chung, Google kernelCTF) – https://github.com/J-jaeyoung/bad-epoll
- Commit de correction en amont a6dc643c6931 (24/04/2026) ; commit à l'origine du bogue 58c9b016e128 (08/04/2023, branche principale v6.4)
- Bug apparenté : CVE-2026-43074 (même commit à l'origine du problème, corrigé séparément)