
cve-2026-43499 — Mis à jour !
PD2229B的43499(ghostlock)可行性研究
Résumé de l'échec de l'exploitation de GhostLock sur PD2229 (SM8475, 5.10.233 GKI)
一、Faits concernant la vulnérabilité et l'appareil
1.1 Informations de base sur CVE-2026-43499 (GhostLock)
| Élément | Valeur |
|---|---|
| Type de vulnérabilité | Use-After-Free sur la pile dans le chemin rt_mutex / futex PI |
| Version d'introduction | Linux 2.6.39-rc1 (mai 2011, commit 8161239a8bcc) |
| Version corrigée | Mainline 7.1 (commit 3bfdc63936dd), branches stables : 6.1.175 / 6.6.140 / 6.12.86 / 6.18.27 / 7.0.4 |
| Prérequis | CONFIG_FUTEX_PI=y (activé par défaut sur les noyaux grand public) |
| CVSS | 7.8 High |
| Stabilité de l'exploitation | 97 % sur la chaîne originale de NebuSec, root en ~5 secondes |
| Prime kernelCTF | 92 337 $ USD |
Plage de noyaux affectés :
- 2.6.39 ≤ Linux < 6.1.175 ✅ Affecté
- 6.2 ≤ Linux < 6.6.140 ✅ Affecté
- 6.7 ≤ Linux < 6.12.86 ✅ Affecté
- 6.13 ≤ Linux < 6.18.27 ✅ Affecté
- 6.19 ≤ Linux < 7.0.4 ✅ Affecté
- Android GKI 5.10 absent de toutes les branches corrigées → le 5.10.233 du PD2229 est théoriquement affecté
1.2 Mesures effectuées sur l'appareil PD2229
| Élément | Valeur |
|---|---|
| SoC | Qualcomm SM8475 (Snapdragon 8 Gen 1 Plus) |
| Version du noyau | 5.10.233-gki-g6e61de9f5b58 #1 SMP PREEMPT (24 nov. 2025) |
| Version Android | 15 (OriginOS 5) |
| Date de compilation | 25/11/2025 |
| Correctifs Android | 01/11/2025 |
CONFIG_FUTEX_PI | y ✅ |
CONFIG_UNMAP_KERNEL_AT_EL0 | y (KPTI activé) |
kptr_restrict | enforced |
CONFIG_IO_URING | y ✅ (confirmé par les symboles vmlinux, et seccomp n'intercepte pas io_uring_setup) |
二、Chaîne d'exploitation idéale vs progression réelle sur PD2229
2.1 Chaîne originale de NebuSec (réussie sur x86_64 / Pixel 10)
1. Contournement KASLR → timing prefetch / PR_SET_MM_MAP auxv
2. Déclenchement UAF → interblocage PI à trois threads → FUTEX_CMP_REQUEUE_PI retourne -EDEADLK
3. Récupération de pile → PR_SET_MM_MAP copie auxv dans le cadre de pile du waiter
4. Écriture limitée rb_erase → écrasement de inet6_protos[IPPROTO_UDP]
5. CEA + ROP → détournement du flux de contrôle
6. Bascule core_pattern → shell root (taux de réussite 97 %)
2.2 Progression réelle de chaque étape sur PD2229
| Étape | Statut | Description |
|---|---|---|
| 1. Contournement KASLR | ✅ Implémenté | Canal auxiliaire perf_event_open + échantillonnage callchain (méthode identique à l'adaptation OPPO Find X6 Pro 5.15.149) |
| 2. Déclenchement UAF | ✅ Implémenté | Interblocage PI à trois threads réussi, FUTEX_CMP_REQUEUE_PI retourne -EDEADLK |
| 3. Primitive de récupération de pile | ❌ Échec architectural | Les cadres de pile de tous les appels système connus ne chevauchent pas le waiter (voir section 3) |
| 4. Écriture limitée rb_erase | ❌ Bloquée | Prérequis non satisfaits |
| 5. Écrasement inet6_protos | ❌ Non commencée | Dépend de l'étape 4 |
| 6. ROP / détournement du flux de contrôle | ❌ Non commencé | Dépend de l'étape 5 |
| 7. Shell root | ❌ Non commencé | Dépend de l'étape 6 |
三、Résultats de l'énumération exhaustive des primitives de récupération de pile (mesures PD2229)
3.1 Calculs clés de la disposition des cadres de pile
Profondeur totale du chemin futex :
__arm64_sys_futex 0x90
+ do_futex 0xc0
+ futex_wait_requeue_pi 0x1b0
= 0x300
Position du waiter = SYS_SP - 0x300 + 0x20 = SYS_SP - 0x2e0
Chemin pselect :
cadre de pile core_sys_select 0x1c0, stack_fds à sp+0x50
Plage couverte : à partir de SYS_SP - 0x1c0 + 0x50 = SYS_SP - 0x170
Écart avec le waiter (SYS_SP - 0x2e0) de 0x170 (368 octets) → pas de chevauchement
3.2 Les 17 méthodes d'écriture de pile essayées
| # | Méthode | Appel système | Résultat PD2229 | Raison principale de l'échec |
|---|---|---|---|---|
| 1 | stamp_prctl | PR_SET_MM_MAP | ❌ EPERM | Interception matérielle Android |
| 2 | stamp_pselect | pselect6 (NFDS=320) | ❌ Pas de chevauchement | waiter 120B sous fd_set |
| 3 | stamp_pselect | pselect6 (NFDS>336) | ❌ Allocation tas | Chemin kvmalloc |
| 4 | stamp_socket | MCAST_JOIN_SOURCE_GROUP | ❌ Couverture insuffisante | Écrit uniquement le champ lock |
| 5 | stamp_sendmsg | sendmsg | ❌ À 80B du waiter | Profondeur de cadre 0x90 insuffisante |
| 6 | stamp_sendmmsg | sendmmsg | ❌ À 112B du waiter | Cadre de pile insuffisant |
| 7 | stamp_recvmmsg | recvmmsg | ❌ Zéroise task/lock | Le cadre 0x1d0 corrompt les pointeurs critiques |
| 8 | stamp_process_vm | process_vm_writev | ❌ Pas de chevauchement | Pile du thread fils allouée séparément |
| 9 | stamp_keyctl | KEYCTL_INSTANTIATE_IOV | ❌ EOPNOTSUPP | Appel système non pris en charge + cadre 0x40 |
| 10 | stamp_tcp | TCP_ZEROCOPY_RECEIVE | ❌ Cadre insuffisant | Profondeur estimée insuffisante |
| 11 | stamp_futex | FUTEX_CMP_REQUEUE_PI récursif | ❌ Logiquement impossible | Corrompt la fenêtre UAF |
| 12 | binder ioctl | BINDER_WRITE_READ | ❌ EACCES | Le shell n'a pas les droits sur /dev/binder |
| 13 | poll | poll | ❌ Allocation tas | pollfd sur le tas |
| 14 | epoll_wait | epoll_wait | ❌ Cadre trop peu profond | Cadre de pile 0xE0 |
| 15 | sched_setattr | sched_setattr | ❌ Profondeur insuffisante | Cadre de pile 0xb0 |
| 16 | timerfd_settime | timerfd_settime | ❌ Pas de copie de pile | Pas de grand tampon de pile |
| 17 | io_uring_register | IORING_REGISTER_* | ❌ Double échec | ①Cadre de pile de seulement 0xF0, cible copy_from_user fixe à sp+0x8 (écart de 424 octets avec le sp+0x1D0 du waiter) ; ②Bien que io_uring_setup ne soit pas intercepté par seccomp (retourne EFAULT et non ENOSYS), la disposition de la pile ne correspond pas |
17/17 ont tous échoué.
3.3 Cause profonde de l'échec
La disposition de la pile produite par le compilateur du SM8475 5.10 GKI du PD2229 (PGO + LTO + BOLT) fait que stack_fds de core_sys_select et rt_mutex_waiter de futex_wait_requeue_pi ne se chevauchent pas architecturalement. C'est un fait objectif déterminé par le compilateur, et non un problème de technique d'exploitation.
Le dépôt JoinChang indique clairement : « The pselect stack overlay only works when the freed rt_mutex_waiter lands within the user-controllable region of the stack_fds buffer » — le PD2229 ne satisfait pas cette condition.
四、Analyse comparative des dépôts de référence publics
NebuSec/CyberMeowfia — Framework d'exploitation original
- Dépôt : https://github.com/NebuSec/CyberMeowfia
- Cible : x86_64 Linux / Pixel 10 (6.x GKI)
- Récupération de pile :
PR_SET_MM_MAPcopie auxv sur la pile du noyau - Taux de réussite : 97 %, ~5 secondes pour un [shell root]
- Applicabilité au PD2229 : ❌
PR_SET_MM_MAPest intercepté par EPERM sur Android
JoinChang/ghostlock-oneplus — Jailbreak BL OnePlus
- Dépôt : https://github.com/JoinChang/ghostlock-oneplus
- Appareils vérifiés :
- OnePlus Ace 6T (PLR110, SM8845) — 6.12.38 GKI ✅
- OnePlus 15 (PLK110, SM8845) — 6.12.23 GKI ✅
- Points techniques :
- Extraction automatique des offsets : kallsyms (28) + BTF (57) + dérivés (9) + constantes (12) = 103/103
- Chevauchement de pile pselect, diff SP = -64
PSELECT_SHIFT = -2- Chaîne d'exploitation : futex UAF → waiter falsifié → pselect contrôle la pile → écriture limitée rb_erase → selinux_state.enforcing=0 → écrasement cred par init_cred
- Déclaration explicite d'impossibilité : « Not Feasible (stack layout incompatible) » — applicable uniquement aux noyaux où pselect stack_fds chevauche le waiter
- Applicabilité au PD2229 : ❌ Génération de noyau incompatible (6.12 vs 5.10), et disposition de pile sans chevauchement
p2p3p/GhostLock-for-OnePlus — Exploitation complète OnePlus 6.12
- Dépôt : https://github.com/p2p3p/GhostLock-for-OnePlus
- Vérifié : OnePlus Ace 6T (SM8845, 6.12.38) ✅
- Applicabilité au PD2229 : ❌ Comme JoinChang, génération de noyau incompatible
YuKongA/ghostlock-oplus — OPPO Find N5/X8
- Dépôt : https://github.com/YuKongA/ghostlock-oplus
- Noyau : 6.6.118 GKI
- Applicabilité au PD2229 : ❌ Génération de noyau incompatible
Adaptation OPPO Find X6 Pro (PGEM10) — 5.15.149
- Appareil : SM8550, 5.15.149-android13, Android 15
- Progression : ✅ Contournement KASLR (perf_event_open + échantillonnage callchain) ; étapes suivantes non publiées intégralement
- Importance : prouve que le contournement KASLR est possible sur GKI 5.15, mais la phase de récupération de pile n'a pas été validée publiquement
pubglite55/oppo-ghostlock — OPPO Find N2
- Dépôt : https://github.com/pubglite55/oppo-ghostlock
- Appareil : OPPO Find N2 (CPH2413, SM8475)
- Noyau : 5.10.236-android12-9-o-g74d132f4467a
- Android : 16 (BP2A.250605.015)
- Implémenté :
- ✅ Firefox CVE-2026-10702 AAW (étape 1)
- ✅ Contournement KASLR (calcul direct de kaslr_base)
- ✅ Déclenchement GhostLock FUTEX (FUTEX_CMP_REQUEUE_PI ret=0)
- ✅ Fuite mm_struct KernelSnitch
- ✅ Heap-spray sk_buff (4/4 envois réussis)
- ✅ Vérification de 70+ offsets avec IDA Pro
- Blocage principal :
« pselect ne peut pas manipuler la structure waiter — NFDS >336 place fd_set sur le tas ; configfs/ashmem non pris en charge (SET_NAME d'ashmem tronqué) ; tous les autres chemins d'écriture du noyau bloqués (/proc/self/mem, /dev/mem, binder) »
- Relation avec PD2229 : Même plateforme, même génération (SM8475, 5.10.236 vs 5.10.233), seulement 3 sous-versions d'écart, confronté exactement aux mêmes limitations architecturales
harry1080/oppo-ghostlock — OPPO Find N2
- Dépôt : https://github.com/harry1080/oppo-ghostlock
- Appareil : OPPO Find N2 (CPH2413, SM8475)
- Noyau : 5.10.236-android12-9-o-g74d132f4467a
- Android : 16 (BP2A.250605.015)
- Déclaration publique de la communauté :
« Sur la version exploitable du pixel10, pselect stack_fds chevauche exactement rt_waiter sur la pile du noyau ; c'est en réalité la partie la plus délicate. Sur le noyau de l'OPPO findN2, les piles de ces deux appels ne se chevauchent pas du tout, ou le chevauchement n'est pas contrôlable ; il faut trouver une autre méthode pour contrôler la pile, en utilisant d'autres appels système avec une pile noyau contrôlable pour construire la pile. Une simple adaptation des offsets ne peut pas réussir ; le rt_waiter d'OPPO ne chevauche pas du tout pselect stack_fds »
- Relation avec PD2229 : Même SM8475 5.10 GKI que le PD2229, conclusion entièrement applicable
4.3 Tableau comparatif global des dépôts de référence
| Dépôt | Appareil | SoC | Noyau | Méthode de récupération de pile | Statut | Réutilisabilité PD2229 |
|---|---|---|---|---|---|---|
| NebuSec/CyberMeowfia | Pixel 10 | - | 6.x | PR_SET_MM_MAP | ✅ 97 % | ❌ Interception Android |
| JoinChang/ghostlock-oneplus | OnePlus Ace 6T | SM8845 | 6.12.38 | pselect (diff SP=-64) | ✅ Vérifié | ❌ Génération de noyau incompatible |
| p2p3p/GhostLock-for-OnePlus | OnePlus Ace 6T | SM8845 | 6.12.38 | pselect | ✅ Vérifié | ❌ Génération de noyau incompatible |
| YuKongA/ghostlock-oplus | Find N5/X8 | - | 6.6.118 | pselect | ✅ | ❌ Génération de noyau incompatible |
| Adaptation OPPO Find X6 Pro | Find X6 Pro | SM8550 | 5.15.149 | perf KASLR + ? | 🟡 KASLR ✅, suite non publiée | ❌ Plateforme différente |
| pubglite55/oppo-ghostlock | Find N2 | SM8475 | 5.10.236 | Énumération échouée | ❌ Blocage principal | ⚠️ Même plateforme, même génération, même destin |
| harry1080/oppo-ghostlock | Find N2 | SM8475 | 5.10.236 | Énumération échouée | ❌ Architecturalement impossible | ⚠️ Même plateforme, même génération, même destin |
| PD2229 (ce rapport) | PD2229 | SM8475 | 5.10.233 | Les 17 candidats ont tous échoué | ❌ Architecturalement impossible | — |
五、Symboles et offsets clés du noyau (mesures vmlinux PD2229)
Adresse de base statique
0xffffffc008000000, ajouter le slide KASLR au moment de l'exécution.
| Symbole | Adresse | Utilisation |
|---|---|---|
rt_mutex_start_proxy_lock | 0xffffffc00822baa8 | Point d'entrée du déclenchement de la vulnérabilité |
futex_wait_requeue_pi | 0xffffffc0082d7df4 | Allocation du waiter, cadre de pile 0x1b0 |
__arm64_sys_futex | 0xffffffc0082dfe9c | Cadre de pile 0x90 |
do_futex | 0xffffffc0082d0768 | Cadre de pile 0xc0 |
core_sys_select | 0xffffffc008634cf0 | Cadre de pile pselect 0x1c0 |
____sys_sendmsg | 0xffffffc0093eda88 | Cadre de pile 0x90 |
do_recvmmsg | 0xffffffc0093ef49c | Cadre de pile 0x1d0 |
__arm64_sys_io_uring_register | 0xffffffc008aae328 | Cadre de pile 0x10+0x70 |
__io_uring_register | 0xffffffc008aae5f8 | Cadre de pile 0x80 |
inet6_protos | 0xffffffc00ab0a278 | Cible d'écriture de l'étape 4 |
selinux_state | 0xffffffc00aee8c70 | Cible de désactivation SELinux |
init_task | 0xffffffc00ab0c240 | Source de lecture cred |
Structure rt_mutex_waiter (personnalisation vivo 5.10.233)
struct rt_mutex_waiter {
uint64_t private; // +0x00 (champ privé vivo)
struct rb_node {
uint64_t rb_parent_color; // +0x08
uint64_t rb_right; // +0x10 (ordre inversé par vivo)
uint64_t rb_left; // +0x18
} tree;
struct task_struct *task; // +0x20
struct rt_mutex *lock; // +0x28
};
// Taille totale 0x30 (48 octets)
六、Implémenté vs à implémenter
✅ Infrastructure implémentée
- Contournement KASLR —
perf_event_open+ échantillonnage callchain (méthode identique à OPPO Find X6 Pro 5.15.149) - Déclenchement UAF — Interblocage PI à trois threads, FUTEX_CMP_REQUEUE_PI retourne -EDEADLK
- Table de symboles complète — 103+ symboles vérifiés avec IDA (selon la méthodologie d'extraction 103/103 de JoinChang)
- Disposition de la structure rt_mutex_waiter — Offsets personnalisés vivo confirmés
- Analyse précise de la disposition des cadres de pile — Calcul des profondeurs des chemins futex et pselect/io_uring terminé
- Exclusion exhaustive des 17 candidats de récupération de pile — Matrice complète d'« impossibilité » établie
❌ Non implémenté (blocage principal)
- Primitive de récupération de pile — Disposition de pile du compilateur SM8475 5.10 GKI architecturalement inutilisable
- Primitive d'écriture limitée — rb_erase ne peut pas être déclenché en raison de l'échec de la récupération de pile
- Toutes les étapes suivantes — Blocage en cascade
七、Conclusion finale
⚠️ GhostLock (CVE-2026-43499) n'est pas exploitable sur PD2229 (vivo X Fold+, SM8475, 5.10.233 GKI, Android 15 OriginOS 5).
La cause profonde est la disposition de pile produite par le compilateur SM8475 5.10 GKI (PGO+LTO+BOLT), qui fait que les cadres de pile de tous les appels système connus ne chevauchent pas architecturalement
rt_mutex_waiter. C'est un fait objectif déterminé par le compilateur, et non un problème de technique d'exploitation.
Les cas d'exploitation réussie concernent tous les GKI 6.6/6.12, car la sortie du compilateur de ces noyaux plus récents fait parfaitement chevaucher pselect fd_set et le waiter (diff SP=-64). Le GKI 5.10 ne possède pas cette condition.
Infrastructure établie
- ✅ Primitive de contournement KASLR (canal auxiliaire perf_event_open)
- ✅ 103+ symboles et offsets du noyau
- ✅ Disposition de la structure rt_mutex_waiter
- ✅ Capacité de déclenchement UAF
- ✅ Matrice d'exclusion des 17 candidats de récupération de pile
九、Index des dépôts de référence
| Dépôt | URL | Valeur clé |
|---|---|---|
| NebuSec/CyberMeowfia | https://github.com/NebuSec/CyberMeowfia | Framework d'exploitation original, taux de réussite 97 % |
| JoinChang/ghostlock-oneplus | https://github.com/JoinChang/ghostlock-oneplus | Adaptation réussie GKI 6.12, méthodologie d'extraction des 103 offsets |
| p2p3p/GhostLock-for-OnePlus | https://github.com/p2p3p/GhostLock-for-OnePlus | Chaîne d'exploitation complète GKI 6.12 |
| YuKongA/ghostlock-oplus | https://github.com/YuKongA/ghostlock-oplus | Adaptation OPPO GKI 6.6 |
| pubglite55/oppo-ghostlock | https://github.com/pubglite55/oppo-ghostlock | Référence d'échec même plateforme SM8475 5.10.236 |
| harry1080/oppo-ghostlock | https://github.com/harry1080/oppo-ghostlock | Référence d'échec même plateforme SM8475 5.10.236 |
| Analyse technique NebuSec | https://nebusec.ai/research/ionstack-part-2/ | Détails techniques de la chaîne originale GhostLock |
| Correctif en amont | commit 3bfdc63936dd | Code du correctif |