
Vérificateur de preuve de concept Aarch64 pour CVE-2026-46242 'Bad Epoll', déclenchant la course use-after-free close-vs-close d'epoll du noyau Linux pour valider l'élévation de privilèges locale.
Ce dépôt est un validateur Bad Epoll pour les noyaux aarch64, basé sur un exploit existant déjà pour x86.
Élévation de privilèges locale du noyau Linux via une course (race condition) Use-After-Free dans
epoll
| Champ | Détail |
|---|---|
| CVE | CVE-2026-46242 |
| Surnom | Bad Epoll |
| Type | Use-After-Free (UAF) via une condition de course |
| CVSS | 7.8 (Élevé) |
| Impact | Élévation de privilèges locale → root |
| Noyaux affectés | 5.10 – 6.11 (LTS & COS) |
| Sous-système | fs/eventpoll.c (ep_remove() / chemin de fermeture) |
Une condition de course existe dans le sous-système epoll du noyau Linux lors d'opérations concurrentes close() sur des descripteurs de fichiers surveillés et surveillants. Lorsque deux chemins de fermeture s'exécutent simultanément :
eventpoll via ep_remove().hlist_del_rcu() de l'autre chemin atterrit sur la mémoire déjà libérée.Cela produit une Use-After-Free qui corrompt la liste refs de l'eventpoll récupéré, laissant un pointeur dangling epi->ffd.file dans le waiter epoll survivant — la base de la chaîne d'exploitation complète.
┌─────────────────────────────────────────────────────────┐
│ 1. Fuite KASLR (canal auxiliaire prefetch via libxdk) │
├─────────────────────────────────────────────────────────┤
│ 2. Déclenchement de la course (UAF close-vs-close sur eventpoll) │
│ ├─ Minuteur adaptatif : phases stat/exec calibrent à l'avance │
│ ├─ False-sharing : dup()+close() élargit la fenêtre de course │
│ └─ Oracle : EPOLL_CTL_ADD profondeur-3 → ELOOP ? │
├─────────────────────────────────────────────────────────┤
│ 3. Réclamation (eventpoll libéré → ep_uaf_target) │
│ └─ epi->ffd.file dangling dans ep_uaf_waiter │
├─────────────────────────────────────────────────────────┤
│ 4. Cross-Cache (slab filp → buddy → pipe_buffer) │
│ ├─ Vider la liste partielle par CPU │
│ ├─ Libérer les objets englobants → page slab libérée │
│ └─ Réclamer comme pages de pipe (256 × 4 Ko) │
├─────────────────────────────────────────────────────────┤
│ 5. AAR contraint (fdinfo ino:/sdev: comme oracle de lecture) │
│ ├─ Spray de faux fichiers forge struct file dans le pipe │
│ ├─ Lecture 8 octets : ino: ← i_ino à un décalage contrôlé │
│ ├─ Lecture 4 octets : sdev: ← curseur sigaltstack(sas_ss_sp) │
│ └─ Parcours : init_task → trouver la tâche exploitée → résoudre │
│ files → fdt → fd[] → pipe_buffer → struct page │
├─────────────────────────────────────────────────────────┤
│ 6. Contrôle RIP (détournement f_op→poll → JOP → ROP) │
│ ├─ Forger f_op = virt, f_count = virt - 1 │
│ ├─ Chaîne de pivot JOP fait atterrir rsp sur une page contrôlée │
│ └─ ROP libxdk : commit_creds(init_cred) + changement de ns │
├─────────────────────────────────────────────────────────┤
│ 7. Ret2Usr execve("/bin/bash") en root │
└─────────────────────────────────────────────────────────┘
# aarch64 (cross-compilation ou natif)
aarch64-linux-gnu-gcc -O2 -Wall -pthread -march=armv8-a \
race_check_aarch64.c -o race_check
./race_check [timeout_seconds] # défaut : 300 s (5 min)
./race_check 120 # délai d'expiration de 2 minutes
| Code | Signification |
|---|---|
0 | Course gagnée — le noyau est vulnérable |
1 | Délai d'expiration — course non détectée (faux négatif possible, ne prouve pas que le noyau est corrigé) |
⚠️ Avertissement : Ce dépôt est fourni uniquement à des fins éducatives et de recherche en sécurité autorisée. Toute utilisation non autorisée de cet exploit contre des systèmes que vous ne possédez pas ou pour lesquels vous n'avez pas explicitement l'autorisation de tester est illégale.