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
| É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
二、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
三、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
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_MAP copie auxv sur la pile du noyau
- Taux de réussite : 97 %, ~5 secondes pour un [shell root]
- Applicabilité au PD2229 : ❌
PR_SET_MM_MAP est 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
YuKongA/ghostlock-oplus — OPPO Find N5/X8
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
五、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.
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