
Notas de pesquisa e desenvolvimento de PoC para CVE-2026-43499 (GhostLock) kernel UAF no vivo Y200i Android 14, cobrindo primitivas de recuperação de pilha da cadeia PI de futex e limites de layout de frame.
Dispositivo: vivo Y200i (PD2354C), Snapdragon 4 Gen 2 (SM4450), Android 14 / OriginOS 4 Kernel: 5.10.218-gki-g3a51ea9d5834 (VA de 39 bits, páginas de 4K, KASLR ativado, STACKLEAK=y, sem SVE)
Objetivo: root temporário via CVE-2026-43499 (GhostLock).
Funcionando até agora:
Bloqueado: a primitiva de recuperação de pilha não consegue alcançar o rb_node do rt_mutex_waiter.
Números-chave (idênticos em dois pacotes de firmware independentes):
__arm64_sys_futex 0xe0
do_futex 0xc0 (NÃO inlined - existe um bl do_futex)
futex_wait_requeue_pi 0x1b0 (waiter em sp+0x20)
=> profundidade da cadeia futex T0-0x330
__arm64_sys_pselect6 0xa0 core_sys_select 0x1c0 (fd_set em sp+0x50) => profundidade da cadeia pselect T0-0x210, janela controlável de apenas 120 bytes => lacuna de 0x120, arquiteturalmente não sobreposta
layout do waiter (5.10 compacto, corresponde ao PFEM10): +0x18 pi_tree_entry.__rb_parent_color <- o que rt_mutex_adjust_prio_chain percorre +0x20 pi_tree_entry.rb_right +0x28 pi_tree_entry.rb_left +0x30 task +0x38 lock +0x40 prio +0x48 deadline
Evidência 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)
Como copy_from_user escreve em direção a endereços mais altos, cobrir pi_tree_entry requer que a base da cópia seja <= T0-0x318.
Caminhos esgotados: pselect6/core_sys_select T0-0x210 -> faltam 0x120 poll/do_sys_poll janela termina em T0-0x344, máx 0xf0B (N_STACK_PPS=30) -> faltam 0x14 rt_sigreturn (fpsimd) T0-0x300 -> alcança apenas waiter+0x30 rt_sigreturn (SVE) T0-0x310 -> cobriria waiter+0x10, mas esta CPU não tem SVE; o kernel rejeita registros de sigframe SVE com -EINVAL compat rt_sigreturn / vfp T0-0x2c0 -> ainda mais raso
Varredura completa do kernel de todos os locais de copy_from_user: 655 no total, 118 alcançáveis, profundidade máxima 0x300 (bpf_prog_get_info_by_fd, também restrito por CAP_BPF). Necessário 0x318.
Conclusão: a geometria de pilha deste kernel atinge no máximo 0x300 para copy_from_user baseado em pilha; cobrir pi_tree_entry requer 0x318. Não é uma questão de ajuste - é uma diferença de layout de frame em tempo de compilação. do_futex não está inlined aqui, ao contrário do PFEM10 (5.10.236, Clang 12.0.5), provavelmente um modelo de custo de inlining diferente.
Procurando por:
Referência: https://github.com/x-spy/CVE-2026-43499-popsicle