
INACHEVÉ/WIP - POC de recherche CVE-2026-43499 (IonStack/GhostLock) pour Samsung SM-T878U / gts7l. Déclencheur + géométrie vérifiés, PAS encore de root fonctionnel.
[!CAUTION] CE PROJET EST INACHEVÉ — IL NE FONCTIONNE PAS ENCORE. Il n'existe aucun root fonctionnel sur aucun appareil à la date du 2026-10-06. Ne vous attendez pas à ce que le démarrage rapide ci-dessous réussisse. Lisez État actuel avant de compiler ou d'exécuter quoi que ce soit.
[!WARNING] STATUT : TRAVAIL EN COURS — ring 1 non atteint
- Non obtenu : un
rootpersistant ou même ponctuel sur SM-T878U.- Dernier échec vérifié : la charge utile de récupération de pile n'atteint jamais le chemin d'écriture du noyau. Sur environ 470 exécutions instrumentées, le verrou forgé n'est jamais observé comme acquis à
rtmutex.c:585, donc l'écriture*(ASHMEM_MISC_FOPS) = fake_fopsne s'exécute jamais.- Ancien blocage, désormais résolu : la forensique de crash était auparavant indisponible pour
uid 2000 shell(/proc/kmsg,/proc/last_kmsg,/sys/fs/pstore,dmesg→ tousEACCES). Un miroir de journal durablewrite()+fsync()(IONSTACK_LOG_MIRROR) survit désormais àCONFIG_PANIC_ON_OOPS=y, de sorte qu'une exécution ayant subi un panic laisse tout de même une trace complète.- Voir
docs/RTMUTEX_WEAPONIZATION.md§15.16–§15.18 pour la piste de preuves complète.
Preuve de concept de re-root en C pur, assistée par hôte, pour Samsung Galaxy Tab S7 (SM-T878U / gts7l) contre CVE-2026-43499 (IonStack / GhostLock).
La chaîne d'exécution n'utilise que des composants natifs C/ELF. Elle ne nécessite ni
Python, ni Java, ni DEX, ni app_process, ni JVM sur la cible Android. ADB est utilisé
pour le déploiement et la vérification.
Aucun root n'a été obtenu. Cette section constitue le compte rendu de référence et à jour
de l'avancement de la chaîne (dernière révision le 2026-10-06). Tout ce qui suit est mesuré
sur du matériel réel (SM-T878U, T878USQS8DXE1, noyau 4.19.113-27114284), et non de la théorie.
| Étape | Statut | Preuve |
|---|---|---|
| Identité de la cible + fuite KASLR | fonctionnel | [reroot] LEAK_OK kaslr_base=… task=… (canal auxiliaire perf) |
Déclencheur CVE : FUTEX_CMP_REQUEUE_PI → -EDEADLK | fonctionnel | [*] requeue ret=-1 errno=35 — EDEADLK == 35 sous Linux |
Le rollback bogué laisse un pi_blocked_on pendant | correspond au correctif amont | le correctif amont 3bfdc63936dd remplace current->pi_blocked_on → waiter->task->pi_blocked_on |
Disposition de struct rt_mutex_waiter (4.19) | vérifiée depuis les sources | tree_entry@0x00 pi_tree_entry@0x18 task@0x30 lock@0x38 prio@0x40 deadline@0x48 |
Géométrie de pile paint == rt_waiter + 0x28 | vérifiée 4× dont objdump | rt_waiter = do_futex_sp+0xC0 ; address = ___sys_sendmsg_sp+0xB8 |
| Forensique de crash durable | fonctionnel | la trace IONSTACK_LOG_MIRROR write()+fsync() survit à un redémarrage après panic |
| Étiquette d'identité par page de fragment et par message | fonctionnel | reclaim-scan tag=1 sent=8201 range=1..8201 ok=8192 bad=0 dup=0 undecoded=0 absent=9 |
| Balayage de file : le noyau a écrit 0 octet dans les 8192 pages de fragments en file | vérifié | 256 Mo comparés octet par octet à la charge utile, hits=0 |
rt_mutex_adjust_prio_chain atteint le chemin d'écriture | vérifié depuis le désassemblage | top_waiter == NULL ⇒ requeue reste true ⇒ 664/682/685/716-725 structurellement atteignables |
page-dump et les 45 observations ring1-page rapportent toutes
first_diff=8000 (pristine), owner_cpu=00000000, case1_gate=0, et
lock_root/lock_leftmost exactement égaux à la valeur de la charge utile. Le parcours n'a
jamais été observé prenant fake_lock->wait_lock à rtmutex.c:585, donc
664/682/685/716-725 — la seule branche capable d'écrire dans
*(ASHMEM_MISC_FOPS) — ne s'est jamais exécutée.
Notez que _raw_spin_trylock()/_raw_spin_unlock() passent par
des helpers hors ligne et que cet arbre vendeur n'a aucune surcharge arm64 de queued_spin_unlock,
donc wait_lock.val == 1 est le témoin fiable de 585 et
owner_cpu != 0 n'en est qu'un témoin secondaire.prctl(PR_SET_MM, PR_SET_MM_MAP, …). Ce noyau est livré avec
# CONFIG_CHECKPOINT_RESTORE is not set, donc cet appel système est compilé hors du noyau.
Il n'utilise pas non plus sendmsg — notre véhicule — ce qui est très probablement la cause racine de (1).ring1-read ne s'est jamais exécuté. La seule relecture en espace utilisateur de l'anneau 1
(configfs_read_once(fd, data_addr(ASHMEM_MISC_FOPS), …)) se trouve derrière la
barrière de balayage de file et derrière la valeur par défaut MARKER du harnais, qui s'arrête 8 s
plus tôt à ring1-page. Chaque exécution ayant atteint la barrière est morte entre
page-dump tag=pre-arm et page-dump tag=post-arm.664/682/685 peuvent s'achever à l'intérieur de notre
propre page — IONSTACK_FOPS_WAIT_LOCK_WORD=0 avec
IONSTACK_PAINT_WAITER_TASK_MODE=fake-task — et lire
page-dump tag=post-arm / ring1-lock585 pour wait_lock=00000001.ring1-read : lancer avec IONSTACK_RECLAIM_SCAN_QUEUE non défini et
MARKER='ring1-read|…' afin que le harnais ne s'arrête pas à ring1-page.IONSTACK_RECLAIM_TAG=1 et comparer
pipe_tag à msg_tag dans page-dump. Toutes les pages de fragment sont des copies
identiques octet pour octet de la charge utile, donc first_diff seul ne permet pas de les distinguer.IONSTACK_FOPS_WAIT_LOCK_WORD sur une base correctement posée — wlw=0 vs wlw=1 avec IONSTACK_RECLAIM_TAG maintenu constant. La
corrélation antérieure était biaisée par le fait que les deux variables variaient ensemble.pselect6 res_in/res_out depuis le port K40 4.19.fops.c:3157 reason=selinux_write ret=-1 errno=22 EINVAL — toujours non résolu.