
Repositório de pesquisa documentando tentativas de exploração do UAF de futex CVE-2026-43499 no kernel 6.12.38 do Honor YLP-W00, incluindo fontes de PoC, offsets de kernel e análise de cadeias de escalonamento de privilégios malsucedidas.
Status da pesquisa: vulnerabilidade confirmada como acionável, PI walk bem-sucedido sem crash, mas cadeia completa de escalação de privilégios não implementada. Aguardando atualização upstream.
Este repositório documenta o processo completo de pesquisa para exploração temporária de privilégios do CVE-2026-43499 no tablet Honor YLP-W00 (kernel 6.12.38, +pgo+bolt+lto+mlgo).
Acionamento da vulnerabilidade bem-sucedido (EDEADLK), PI chain walk bem-sucedido (sched_setattr=0, sem crash), mas a compilação PGO causou inlining de do_futex, fazendo com que todos os carriers de recuperação de pilha falhassem; a primitiva de escrita late_refs do CyberMeowfiaNS também não conseguiu atingir o alvo devido à incompatibilidade de geometria do slab.
| Item | Valor |
|---|---|
| Modelo | Honor YLP-W00 (tablet) |
| Sistema | HONORYLP-W00/10DLDLD170SP3C00E144 |
| Versão do sistema | 10.0.0.170 (MagicOS 10.0) |
| Kernel | 6.12.38-android16-5-gfde7767f6ef6-abogki481467632-4k |
| Compilação | +pgo,+bolt,+lto,+mlgo (clang 19.0.1) |
| Kernel SHA-256 | 48b622a20a700cdde0b8f2f6e83959df00a7efedf52f347377cf542f7b58948e |
| Bootloader | Bloqueado |
| SELinux | Enforcing |
| Randomização de kstack | Desativada |
| ashmem | Reescrito em Rust |
| MTE | Suporte de hardware mas KASAN não habilitado |
A auditoria do CyberMeowfiaNS confirmou VULNERABLE_PATTERN_PRESENT. Há dois casos de sucesso no mesmo kernel SHA-256 (honor-mt6993, honor8e5), mas eles usaram a primitiva de escrita late_refs, que não pôde ser reproduzida neste dispositivo (ver detalhes abaixo).
O kernel Honor 6.12.38 foi compilado com +pgo+bolt+lto+mlgo, fazendo com que __arm64_sys_futex chame diretamente futex_wait_requeue_pi, pulando a camada intermediária do_futex. A cadeia de chamadas do futex passou de três camadas padrão para duas camadas:
GKI padrão: __arm64_sys_futex -> do_futex -> futex_wait_requeue_pi
Este dispositivo: __arm64_sys_futex -> futex_wait_requeue_pi (do_futex inlined)
Isso faz com que o waiter fique em uma posição de pilha mais rasa (profundidade 0x130 em vez do padrão 0x1b0+), e a geometria de cobertura de todos os carriers padrão de recuperação de pilha não corresponde.
| Campo | Offset | Tamanho |
|---|---|---|
| tree_entry (rb_node) | +0x00 | 24B |
| pi_tree_entry (rb_node) | +0x18 | 24B |
| lock | +0x38 | 8B |
| prio | +0x44 | 4B |
| deadline | +0x48 | 8B |
| task | +0x50 | 8B |
| ww_ctx | +0x58 | 8B |
| Tamanho total | 0x70 | 112B |
| Símbolo | Offset |
|---|---|
| init_task | 0x023ecf00 |
| init_cred | 0x02402cb0 |
| root_task_group | 0x0261a740 |
| selinux_state.enforcing | 0x026663c8 |
| rb_erase | 0x00bce274 |
| rt_mutex_adjust_prio_chain | 0x115060c |
| commit_creds | 0x00b89c10 |
| worker_thread | 0x00adfef8 |
| remove_waiter | 0x0112b20 |
Confirmação do acionamento da UAF e PI walk bem-sucedido em safe mode:
[futex] CMP_REQUEUE_PI ret=-1 errno=35 (EDEADLK) ← Acionamento da UAF bem-sucedido
[futex] consumer sched_setattr ret=0 errno=0 ← PI walk bem-sucedido, sem crash
O dispositivo permaneceu online, boot_id inalterado, SELinux ainda Enforcing. rb_erase escreveu em um endereço válido mas inútil.
Carriers de recuperação de pilha tentados:
| Carrier | Princípio | Resultado |
|---|---|---|
| pselect | Cópia de pilha do fd_set | shift=26 (inlining PGO), capacidade do fd_set insuficiente |
| MCAST_JOIN_SOURCE_GROUP | Cópia de pilha de 0x108 bytes | WAITER_OFF=0x308 >> 0x108, sem sobreposição |
| adjtimex | Cópia de pilha da estrutura timex | buf depth 0x118 < waiter 0x130, sem sobreposição |
| io_submit | Cobertura de pilha do struct iocb | Cobre waiter[0x28..0x67], lock@0x58 fora do intervalo |
| PR_SET_MM_MAP | Escrita na pilha via prctl | EPERM |
| Entrega de sinal (do_signal) | Salvamento de pilha do pt_regs | Frame cobre waiter[0x00..0x28], task@0x50 e lock@0x58 sobrescritos por outros frames com valores inválidos, crash |
| rt_sigreturn | fpsimd vregs 512B | No 6.12.38 usa ldtr para carregar na área per-cpu, não passa pela pilha do kernel |
Obstáculo central: o waiter está na profundidade 0x130, tree_entry(+0x00) e pi_tree_entry(+0x18) podem ser parcialmente cobertos por carriers, mas task(+0x50) e lock(+0x58) estão mais profundos, e nenhum carrier conhecido consegue alcançá-los. Cobrir tree_entry só faz o rb_erase seguir um caminho vazio (escrever NULL), não sendo possível direcioná-lo ao endereço alvo.
O CyberMeowfiaNS usa uma abordagem completamente diferente, contornando o problema de recuperação de pilha:
Toda a cadeia de pré-requisitos bem-sucedida:
--info passou: verificação de identidade do kernel bem-sucedida--check passou: pré-verificação do carrier DSO (libdumpstateaidl.so) confirmada
Corrida late_refs falhou:
reclaim_hits=0Causa raiz da falha: incompatibilidade de geometria do slab.
A função ep_get_upwards_depth_proc não existe no 6.12.38 (específica do kernel de referência 6.12.58). Mas ep_loop_check_proc de fato escreve em eventpoll.gen (+0xa8), então essa não é a causa direta.
O tamanho da estrutura eventpoll é 0xdc0 (3520 bytes), alocada de kmalloc-4k (order=3, slab de 32KB, 8 objetos). A suposição do código de eventpoll_size=0xd0 (208 bytes) está errada.
eventpoll_epi (epitem) tem 128 bytes, order=0, página de 4KB, 32 objetos por página. O late_refs libera apenas 1-2 epitems por rodada, insuficiente para esvaziar uma página inteira de 4KB e permitir que o page allocator a recupere.
O late_refs requer recuperação de página cross-cache: página de epitem liberada → page allocator → página SKB order-3. Mas isso requer que todos os 32 epitems da mesma página sejam liberados, e o layout do grafo epoll do código não garante isso.
O kernel de referência 6.12.58 pode ter configuração SLUB ou layout de slab diferente, tornando a recuperação cross-cache mais fácil de acionar.
| Arquivo | Descrição | Tamanho |
|---|---|---|
firmware/boot_10.0.0.170.img | boot.img da versão de sistema 10.0.0.170 | 96 MB |
firmware/honor_kernel_6.12.38.img | Kernel ELF extraído do boot.img (com tabela de símbolos) | 44 MB |
firmware/libdumpstateaidl_honor.so | Carrier DSO (extraído do dispositivo) | 52 KB |
O boot.img pode ter a tabela de símbolos do kernel extraída com llvm-nm, e o layout de funções analisado por desmontagem com llvm-objdump.