
Notes de recherche et développement de PoC pour l'UAF du noyau CVE-2026-43499 (GhostLock) sur vivo Y200i Android 14, couvrant les primitives de récupération de pile de chaîne PI futex et les limites de disposition de trame.
Appareil : vivo Y200i (PD2354C), Snapdragon 4 Gen 2 (SM4450), Android 14 / OriginOS 4 Noyau : 5.10.218-gki-g3a51ea9d5834 (VA 39 bits, pages 4K, KASLR activé, STACKLEAK=y, pas de SVE)
Objectif : root temporaire via CVE-2026-43499 (GhostLock).
Fonctionne jusqu'ici :
Bloqué : la primitive de récupération de pile ne peut pas atteindre le rb_node du rt_mutex_waiter.
Chiffres clés (identiques sur deux paquets firmware indépendants) :
__arm64_sys_futex 0xe0
do_futex 0xc0 (PAS inliné - un bl do_futex existe)
futex_wait_requeue_pi 0x1b0 (waiter à sp+0x20)
=> profondeur de chaîne futex T0-0x330
__arm64_sys_pselect6 0xa0 core_sys_select 0x1c0 (fd_set à sp+0x50) => profondeur de chaîne pselect T0-0x210, fenêtre contrôlable seulement 120 octets => écart 0x120, architecturalement non chevauchant
disposition du waiter (5.10 compact, correspond à PFEM10) : +0x18 pi_tree_entry.__rb_parent_color <- ce que parcourt rt_mutex_adjust_prio_chain +0x20 pi_tree_entry.rb_right +0x28 pi_tree_entry.rb_left +0x30 task +0x38 lock +0x40 prio +0x48 deadline
Preuve issue de rt_mutex_adjust_prio_chain : ldr x8, [task, #0x888] ; task->pi_waiters.rb_leftmost sub x8, x8, #0x18 ; rb_entry(node, rt_mutex_waiter, pi_tree_entry)
Comme copy_from_user écrit vers des adresses plus hautes, couvrir pi_tree_entry nécessite que la base de copie soit <= T0-0x318.
Chemins épuisés : pselect6/core_sys_select T0-0x210 -> manque 0x120 poll/do_sys_poll la fenêtre se termine à T0-0x344, max 0xf0B (N_STACK_PPS=30) -> manque 0x14 rt_sigreturn (fpsimd) T0-0x300 -> atteint seulement waiter+0x30 rt_sigreturn (SVE) T0-0x310 -> couvrirait waiter+0x10, mais ce CPU n'a pas de SVE ; le noyau rejette les enregistrements sigframe SVE avec -EINVAL compat rt_sigreturn / vfp T0-0x2c0 -> encore plus superficiel
Scan complet du noyau de tous les sites copy_from_user : 655 au total, 118 atteignables, profondeur max 0x300 (bpf_prog_get_info_by_fd, également restreint par CAP_BPF). Besoin de 0x318.
Conclusion : la géométrie de pile de ce noyau plafonne à 0x300 pour copy_from_user basé sur la pile ; couvrir pi_tree_entry nécessite 0x318. Ce n'est pas un problème de réglage - c'est une différence de disposition de frame à la compilation. do_futex n'est pas inliné ici, contrairement à PFEM10 (5.10.236, Clang 12.0.5), très probablement un modèle de coût d'inlining différent.
Recherche :
Référence : https://github.com/x-spy/CVE-2026-43499-popsicle