
UNFINISHED/WIP - CVE-2026-43499 (IonStack/GhostLock) pesquisa POC para Samsung SM-T878U / gts7l. Trigger + geometria verificados, AINDA SEM root funcional.
[!CAUTION] ESTE PROJETO ESTÁ INACABADO — AINDA NÃO FUNCIONA. Não existe root funcional em nenhum dispositivo até 2026-10-06. Não espere que o início rápido abaixo funcione. Leia Estado atual antes de compilar ou executar qualquer coisa.
[!WARNING] ESTADO: TRABALHO EM CURSO — ring 1 não alcançado
- Não alcançado:
rootpersistente ou sequer de uso único no SM-T878U.- Última falha verificada: o payload de recuperação de pilha nunca chega ao caminho de escrita do kernel. Em ~470 execuções instrumentadas, o lock forjado nunca é observado como adquirido em
rtmutex.c:585, pelo que o armazenamento*(ASHMEM_MISC_FOPS) = fake_fopsnunca é executado.- Antigo bloqueio, agora resolvido: a análise forense de crashes não estava disponível para
uid 2000 shell(/proc/kmsg,/proc/last_kmsg,/sys/fs/pstore,dmesg→ todosEACCES). Um espelho de log durável comwrite()+fsync()(IONSTACK_LOG_MIRROR) sobrevive agora aCONFIG_PANIC_ON_OOPS=y, pelo que uma execução com panic deixa ainda um rasto completo.- Consulte
docs/RTMUTEX_WEAPONIZATION.md§15.16–§15.18 para o rasto completo de evidências.
Prova de conceito de re-root em C puro, assistida por host, para o Samsung Galaxy Tab S7 (SM-T878U / gts7l) contra CVE-2026-43499 (IonStack / GhostLock).
A cadeia de execução usa apenas componentes nativos C/ELF. Não requer
Python, Java, DEX, app_process ou uma JVM no alvo Android. O ADB é usado
para implementação e verificação.
Não foi obtido root. Esta secção é o relato autoritativo e atualizado
do ponto em que a cadeia se encontra (última revisão 2026-10-06). Tudo
abaixo é medido em hardware real (SM-T878U, T878USQS8DXE1, kernel
4.19.113-27114284), não é teoria.
| Etapa | Estado | Evidência |
|---|---|---|
| Identidade do alvo + fuga de KASLR | a funcionar | [reroot] LEAK_OK kaslr_base=… task=… (canal lateral de perf) |
Gatilho da CVE: FUTEX_CMP_REQUEUE_PI → -EDEADLK | a funcionar | [*] requeue ret=-1 errno=35 — EDEADLK == 35 no Linux |
O rollback defeituoso deixa pi_blocked_on pendente | corresponde à correção upstream | upstream 3bfdc63936dd altera current->pi_blocked_on → waiter->task->pi_blocked_on |
Layout de struct rt_mutex_waiter (4.19) | verificado a partir do código-fonte | tree_entry@0x00 pi_tree_entry@0x18 task@0x30 lock@0x38 prio@0x40 deadline@0x48 |
Geometria da pilha paint == rt_waiter + 0x28 | verificado 4× incl. objdump | rt_waiter = do_futex_sp+0xC0; address = ___sys_sendmsg_sp+0xB8 |
| Análise forense durável de crashes | a funcionar | o rasto IONSTACK_LOG_MIRROR com write()+fsync() sobrevive a um reboot por panic |
| Etiqueta de identidade por frag-page por mensagem | a funcionar | reclaim-scan tag=1 sent=8201 range=1..8201 ok=8192 bad=0 dup=0 undecoded=0 absent=9 |
| Varrimento da fila: o kernel escreveu 0 bytes em 8192 frag pages em fila | verificado | 256 MB comparados byte a byte com o payload, hits=0 |
rt_mutex_adjust_prio_chain atinge o caminho de escrita | verificado a partir da desmontagem | top_waiter == NULL ⇒ requeue permanece true ⇒ 664/682/685/716-725 estruturalmente alcançáveis |
page-dump e 45 de ring1-page relatam
first_diff=8000 (pristine), owner_cpu=00000000, case1_gate=0 e
lock_root/lock_leftmost exatamente iguais ao valor do payload. A travessia
nunca foi vista tomando fake_lock->wait_lock em rtmutex.c:585, portanto
664/682/685/716-725 — o único ramo que pode armazenar em
*(ASHMEM_MISC_FOPS) — nunca foi executado.
Observe que _raw_spin_trylock()/_raw_spin_unlock() passam por
helpers out-of-line e esta árvore do vendor não tem nenhum override de
queued_spin_unlock para arm64, então wait_lock.val == 1 é a testemunha
confiável de 585 e owner_cpu != 0 é apenas uma secundária.prctl(PR_SET_MM, PR_SET_MM_MAP, …). Este kernel traz
# CONFIG_CHECKPOINT_RESTORE is not set, então essa syscall é removida na
compilação. Ele também nunca usa sendmsg — nosso veículo — o que é muito
provavelmente a causa raiz de (1).ring1-read nunca foi executado. A única leitura de volta em userspace
do ring 1 (configfs_read_once(fd, data_addr(ASHMEM_MISC_FOPS), …)) fica
atrás do gate de varredura da fila e atrás do padrão MARKER do harness, que
para 8 s antes em ring1-page. Toda execução que chegou ao gate morreu entre
page-dump tag=pre-arm e page-dump tag=post-arm.664/682/685 podem concluir dentro da
nossa própria página — IONSTACK_FOPS_WAIT_LOCK_WORD=0 com
IONSTACK_PAINT_WAITER_TASK_MODE=fake-task — e ler
page-dump tag=post-arm / ring1-lock585 para wait_lock=00000001.ring1-read executar: rodar com IONSTACK_RECLAIM_SCAN_QUEUE não definido e
MARKER='ring1-read|…' para que o harness não pare em ring1-page.IONSTACK_RECLAIM_TAG=1 e comparar
pipe_tag com msg_tag em page-dump. Todas as frag pages são cópias
byte a byte idênticas do payload, então first_diff sozinho não consegue
distingui-las.IONSTACK_FOPS_WAIT_LOCK_WORD em uma base
adequadamente formulada — wlw=0 vs wlw=1 com IONSTACK_RECLAIM_TAG mantido
constante. A correlação anterior foi confundida pelas duas variáveis se movendo juntas.pselect6 de res_in/res_out do port K40 4.19.fops.c:3157 reason=selinux_write ret=-1 errno=22 EINVAL — ainda não resolvido.
| Documento | O que é |
|---|---|
docs/RTMUTEX_WEAPONIZATION.md | Trilha completa de evidências da cadeia rtmutex (maior documento) |
docs/ROOT_CHAIN_THEORY.md | Design da cadeia root de ponta a ponta do ring 0→4 |
docs/PAINT_ORACLE_ANALYSIS.md | Por que o oráculo de stack-paint lê da forma como lê |
docs/PSELECT_GEOMETRY_FINDINGS.md | pselect6 como veículo alternativo de paint |
docs/RING1_RECLAIM_IDENTITY_2026-10-06.md | Tag de identidade de frag-page por mensagem; verificação por varredura da fila |
docs/RING1_585_NEVER_SUCCEEDED_2026-10-06.md | Prova de que rtmutex.c:585 nunca teve sucesso |
docs/RING1_ORACLE_FIX_2026-10-05.md | Correção do oráculo |
docs/RING1_ORACLE_WRONG_FRAGMENT_2026-10-06.md | Por que o fragmento retido foi identificado incorretamente |