
Uma implementação Go de PinTheft (CVE-2026-43494)
Porte em Go do pintheft - LPE de double-free zcopy do RDS. Membro da classe de vulnerabilidade Dirty Frag.
[!IMPORTANT] O Arch Linux é uma das distribuições mais expostas para essa vulnerabilidade, já que está entre as poucas onde o módulo RDS pode tipicamente ser carregado por padrão.
O bug está em rds_message_zcopy_from_user(). A função fixa (GUP-pins) páginas do usuário uma de cada vez via FOLL_GET. Se uma página posterior falhar (por exemplo, uma página de guarda PROT_NONE), o caminho de erro chama put_page() nas páginas já fixadas, então rds_message_purge() chama __free_page() nelas novamente porque op_mmp_znotifier foi anulado mas as entradas op_nents/sg permaneceram intactas. Quando a página ainda tem outras referências, __free_page decrementa silenciosamente a contagem de refs. Cada sendmsg com falha rouba exatamente uma ref da primeira página.
CONFIG_INIT_ON_ALLOC_DEFAULT_ONFixe a página alvo via io_uring REGISTER_BUFFERS, que adiciona GUP_PIN_COUNTING_BIAS (1024) ao refcount através de FOLL_PIN. Roube todas as 1024 refs de pin com envios zcopy com falha. O refcount da página agora é ~1 (apenas o mapeamento PTE). munmap segue o caminho normal de __folio_put, que chama mem_cgroup_uncharge (limpando memcg_data) antes de liberar. Nenhuma verificação bad_page é acionada.
io_uring mantém o struct page* bruto em seu array bvec sem verificações de vivacidade. Após a página ser recuperada como cache de página para um binário suid, IORING_OP_READ_FIXED escreve nosso payload nela através desse ponteiro dangling.
IORING_REGISTER_CLONE_BUFFERS incrementa imu->refs. Um processo filho do daemon (forked) mantém o fd do clone ring aberto - io_buffer_unmap vê refs > 1 e pula unpin_user_folio, prevenindo corrupção do refcount na página liberada.
Fixe na CPU 0, drene entradas PCP obsoletas antes de liberar - nossa página cai no topo quando o alocador de cache de página a pega.
REGISTER_BUFFERS(+1024) -> CLONE_BUFFERS(imu->refs=2) ->
daemon holds clone -> steal 1024 refs -> evict page cache ->
drain PCP -> munmap(free) -> pread(reclaim) ->
READ_FIXED(overwrite) -> verify -> exec -> root
go build -o pintheft-go .
./pintheft-go
Em caso de sucesso, entra em um shell root via PTY. O binário no disco não é tocado.
sudo cp /tmp/.backup_pintheft_<pid> /usr/bin/su && sudo chmod u+s /usr/bin/su
CONFIG_RDS=m, CONFIG_RDS_TCP=m (carregado automaticamente via SO_RDS_TRANSPORT=2)CONFIG_IO_URING=y com io_uring_disabled=0btw, eu amo o Arch Linux :)