Resumo da Falha de Exploração do GhostLock no PD2229 (SM8475, 5.10.233 GKI)
一、Fatos sobre a Vulnerabilidade e o Dispositivo
| Item | Valor |
|---|
| Tipo de vulnerabilidade | Use-After-Free na pilha no caminho rt_mutex / futex PI |
| Versão introduzida | Linux 2.6.39-rc1 (maio de 2011, commit 8161239a8bcc) |
| Versão corrigida | mainline 7.1 (commit 3bfdc63936dd), ramos estáveis: 6.1.175 / 6.6.140 / 6.12.86 / 6.18.27 / 7.0.4 |
| Pré-requisito | CONFIG_FUTEX_PI=y (ativado por padrão nos kernels convencionais) |
| CVSS | 7.8 Alta |
| Estabilidade da exploração | 97% na cadeia original da NebuSec, root em ~5 segundos |
| Recompensa kernelCTF | US$ 92.337 |
Faixa de kernels afetados:
- 2.6.39 ≤ Linux < 6.1.175 ✅ Afetado
- 6.2 ≤ Linux < 6.6.140 ✅ Afetado
- 6.7 ≤ Linux < 6.12.86 ✅ Afetado
- 6.13 ≤ Linux < 6.18.27 ✅ Afetado
- 6.19 ≤ Linux < 7.0.4 ✅ Afetado
- Android GKI 5.10 não está em nenhum ramo de correção → 5.10.233 do PD2229 teoricamente afetado
1.2 Testes reais no dispositivo PD2229
二、Cadeia de exploração ideal vs. progresso real no PD2229
2.1 Cadeia original da NebuSec (bem-sucedida em x86_64 / Pixel 10)
1. Bypass do KASLR → timing de prefetch / PR_SET_MM_MAP auxv
2. Gatilho do UAF → deadlock de dependência PI de três threads → FUTEX_CMP_REQUEUE_PI retorna -EDEADLK
3. Reciclagem da pilha → PR_SET_MM_MAP copia auxv para o frame da pilha do waiter
4. Escrita restrita rb_erase → sobrescreve inet6_protos[IPPROTO_UDP]
5. CEA + ROP → sequestro do fluxo de controle
6. Inversão do core_pattern → shell root (97% de sucesso)
2.2 Progresso real de cada etapa no PD2229
三、Resultados da enumeração exaustiva da primitiva de reciclagem da pilha (testes reais no PD2229)
3.1 Cálculos-chave do layout do frame de pilha
Profundidade total do caminho futex:
__arm64_sys_futex 0x90
+ do_futex 0xc0
+ futex_wait_requeue_pi 0x1b0
= 0x300
Posição do waiter = SYS_SP - 0x300 + 0x20 = SYS_SP - 0x2e0
Caminho pselect:
frame de pilha core_sys_select 0x1c0, stack_fds em sp+0x50
Intervalo coberto: SYS_SP - 0x1c0 + 0x50 = a partir de SYS_SP - 0x170
Diferença para o waiter (SYS_SP - 0x2e0) é 0x170 (368 bytes) → sem sobreposição
3.2 17 métodos de escrita na pilha testados
17/17 todas falharam.
3.3 Causa raiz da falha
O layout da pilha gerado pelo compilador do SM8475 5.10 GKI do PD2229 (PGO + LTO + BOLT) faz com que o stack_fds do core_sys_select e o rt_mutex_waiter do futex_wait_requeue_pi sejam arquiteturalmente não sobrepostos. Este é um fato objetivo determinado pelo compilador, não um problema de técnica de exploração.
O repositório JoinChang afirma explicitamente: "The pselect stack overlay only works when the freed rt_mutex_waiter lands within the user-controllable region of the stack_fds buffer" — o PD2229 não atende a essa condição.
四、Análise comparativa dos repositórios de referência públicos
NebuSec/CyberMeowfia — Framework de exploração original
- Repositório: https://github.com/NebuSec/CyberMeowfia
- Alvo: Linux x86_64 / Pixel 10 (6.x GKI)
- Reciclagem da pilha:
PR_SET_MM_MAP copia auxv para a pilha do kernel
- Taxa de sucesso: 97%, ~5 segundos para [shell root]
- Aplicabilidade ao PD2229: ❌
PR_SET_MM_MAP bloqueado por EPERM no Android
JoinChang/ghostlock-oneplus — Jailbreak do bootloader OnePlus
- Repositório: https://github.com/JoinChang/ghostlock-oneplus
- Dispositivos verificados:
- OnePlus Ace 6T (PLR110, SM8845) — 6.12.38 GKI ✅
- OnePlus 15 (PLK110, SM8845) — 6.12.23 GKI ✅
- Pontos técnicos:
- Extração automática de offsets: kallsyms (28) + BTF (57) + derivados (9) + constantes (12) = 103/103
- Sobreposição de pilha pselect, SP diff = -64
PSELECT_SHIFT = -2
- Cadeia de exploração: futex UAF → waiter falsificado → pselect controla a pilha → escrita restrita rb_erase → selinux_state.enforcing=0 → sobrescrita do cred para init_cred
- Declaração explícita de inviabilidade: "Not Feasible (stack layout incompatible)" — aplicável apenas a kernels onde pselect stack_fds e waiter se sobrepõem
- Aplicabilidade ao PD2229: ❌ Geração do kernel incompatível (6.12 vs 5.10) e layout de pilha sem sobreposição
p2p3p/GhostLock-for-OnePlus — Exploração completa do OnePlus 6.12
YuKongA/ghostlock-oplus — OPPO Find N5/X8
Adaptação OPPO Find X6 Pro (PGEM10) — 5.15.149
- Dispositivo: SM8550, 5.15.149-android13, Android 15
- Progresso: ✅ Bypass do KASLR (perf_event_open + amostragem de callchain); estágios posteriores sem exploração completa divulgada
- Significado: prova que o bypass do KASLR é viável no GKI 5.15, mas o estágio de reciclagem da pilha não foi verificado publicamente
pubglite55/oppo-ghostlock — OPPO Find N2
- Repositório: https://github.com/pubglite55/oppo-ghostlock
- Dispositivo: OPPO Find N2 (CPH2413, SM8475)
- Kernel: 5.10.236-android12-9-o-g74d132f4467a
- Android: 16 (BP2A.250605.015)
- Implementado:
- ✅ Firefox CVE-2026-10702 AAW (Estágio 1)
- ✅ Bypass do KASLR (cálculo direto do kaslr_base)
- ✅ Gatilho do GhostLock FUTEX (FUTEX_CMP_REQUEUE_PI ret=0)
- ✅ Vazamento do mm_struct via KernelSnitch
- ✅ Heap spray sk_buff (envio 4/4 bem-sucedido)
- ✅ Verificação de 70+ offsets no IDA Pro
- Bloqueio central:
"pselect não consegue manipular a estrutura do waiter — com NFDS >336 o fd_set fica no heap; configfs/ashmem não suportados (SET_NAME do ashmem truncado); todos os outros caminhos de escrita no kernel bloqueados (/proc/self/mem, /dev/mem, binder)"
- Relação com o PD2229: Mesma plataforma e mesma geração (SM8475, 5.10.236 vs 5.10.233), diferença de apenas 3 versões menores, enfrentando exatamente as mesmas limitações arquiteturais
harry1080/oppo-ghostlock — OPPO Find N2
- Repositório: https://github.com/harry1080/oppo-ghostlock
- Dispositivo: OPPO Find N2 (CPH2413, SM8475)
- Kernel: 5.10.236-android12-9-o-g74d132f4467a
- Android: 16 (BP2A.250605.015)
- Declaração pública da comunidade:
"pixel10 能利用的版本的 pselect stack_fds 正好和 rt_waiter 在内核栈上重合,这个部分实际上是最麻烦的地方,OPPO findN2 的内核这两个调用的栈部分完全不重合,或者重合也不可控,得找另外的控制栈的方法,要换其他可控内核栈的系统调用来构造栈,简单适配偏移是不可能成功的,oppo 的 rt_waiter 完全与 pselect stack_fds 不重合"
- Relação com o PD2229: Ambos são SM8475 5.10 GKI, a conclusão se aplica integralmente
4.3 Tabela comparativa geral dos repositórios de referência
五、Símbolos-chave do kernel e offsets (medidos no vmlinux do PD2229)
Base estática 0xffffffc008000000, adicionar o slide do KASLR em tempo de execução.
Estrutura rt_mutex_waiter (personalizada do vivo 5.10.233)
struct rt_mutex_waiter {
uint64_t private; // +0x00 (campo privado vivo)
struct rb_node {
uint64_t rb_parent_color; // +0x08
uint64_t rb_right; // +0x10 (ordem trocada pelo vivo)
uint64_t rb_left; // +0x18
} tree;
struct task_struct *task; // +0x20
struct rt_mutex *lock; // +0x28
};
// Tamanho total 0x30 (48 bytes)
六、Implementado vs. a implementar
✅ Infraestrutura implementada
- Bypass do KASLR —
perf_event_open + amostragem de callchain (mesmo método do OPPO Find X6 Pro 5.15.149)
- Gatilho do UAF — Deadlock PI de três threads, FUTEX_CMP_REQUEUE_PI retorna -EDEADLK
- Tabela de símbolos completa — 103+ símbolos verificados via IDA (seguindo a metodologia de extração 103/103 do JoinChang)
- Layout da estrutura rt_mutex_waiter — offsets personalizados do vivo confirmados
- Análise precisa do layout dos frames de pilha — cálculo de profundidade dos caminhos futex e pselect/io_uring concluído
- Exclusão exaustiva de 17 candidatos de reciclagem da pilha — matriz completa de "inviabilidade" estabelecida
❌ Não implementado (bloqueio central)
- Primitiva de reciclagem da pilha — layout de pilha do compilador do SM8475 5.10 GKI torna arquiteturalmente indisponível
- Primitiva de escrita restrita — rb_erase não pode ser acionado devido à falha na reciclagem da pilha
- Todas as etapas subsequentes — bloqueio em cascata
七、Conclusão final
⚠️ GhostLock (CVE-2026-43499) não é explorável no PD2229 (vivo X Fold+, SM8475, 5.10.233 GKI, Android 15 OriginOS 5).
A causa raiz é o layout da pilha gerado pelo compilador do SM8475 5.10 GKI (PGO+LTO+BOLT), que faz com que os frames de pilha de todas as syscalls conhecidas sejam arquiteturalmente não sobrepostos ao rt_mutex_waiter. Este é um fato objetivo determinado pelo compilador, não um problema de técnica de exploração.
Todos os casos de exploração bem-sucedida usam GKI 6.6/6.12, porque a saída do compilador nesses kernels mais novos faz o fd_set do pselect se sobrepor perfeitamente ao waiter (SP diff=-64). O GKI 5.10 não possui essa condição.
Infraestrutura estabelecida
- ✅ Primitiva de bypass do KASLR (canal lateral perf_event_open)
- ✅ 103+ símbolos do kernel e offsets
- ✅ Layout da estrutura rt_mutex_waiter
- ✅ Capacidade de gatilho do UAF
- ✅ Matriz de exclusão de 17 candidatos de reciclagem da pilha
九、Índice de repositórios de referência