Um script Python de 732 bytes. Sem race condition. Sem offset de kernel. Root em qualquer distro Linux mainstream dos últimos 9 anos.
Parece exagero? Eu também achei — até ler o disclosure completo do Copy Fail, publicado em 29 de abril de 2026 e já com mais de 1.000 pontos no Hacker News. O CVE-2026-31431 é o tipo de bug que faz engenheiro de segurança perder o sono: uma falha de lógica pura no kernel Linux que existe desde 2017 e que ninguém percebeu por quase uma década.
Diferente do Dirty Cow ou do Dirty Pipe, que dependiam de race conditions ou de versões específicas do kernel, o Copy Fail funciona de forma determinística. Você roda o script, ele escreve 4 bytes na page cache de qualquer arquivo legível pelo usuário, e pronto — game over.
Vamos entender como isso funciona, por que demorou tanto para ser encontrado, e o que você precisa fazer agora para se proteger.
A cadeia de ataque: três subsistemas, um bug
O Copy Fail não é um buffer overflow clássico nem uma race condition. É o que o pesquisador chamou de “straight-line logic flaw” — um erro na lógica do código que se manifesta de forma confiável, sem precisar “ganhar” nenhuma corrida contra o kernel.
A cadeia de ataque encadeia três subsistemas do kernel Linux:
| Subsistema | Papel no ataque |
|---|---|
| AF_ALG (socket interface) | Expõe operações criptográficas para userspace sem privilégios |
| splice() | Transfere dados entre file descriptors usando referências diretas à page cache — sem copiar os dados |
| algif_aead.c (crypto template) | Operação in-place que aponta req->src = req->dst, colocando páginas da page cache no scatterlist de destino |
A mágica (ou o horror, dependendo da perspectiva) acontece quando esses três se encontram.
Como o kernel acabou escrevendo onde não devia
Para entender o bug, preciso explicar um pouco de história.
2011 — O algoritmo authencesn foi adicionado ao kernel (commit a5079d084f8b) para suportar IPsec ESP com Extended Sequence Numbers. Ele usa o buffer de destino como scratch space temporário para rearranjar bytes do AAD (Associated Authenticated Data). Nessa época, source e destination eram scatterlists separados, então nenhum dado externo era afetado.
2015 — O algif_aead.c ganhou suporte a AEAD via AF_ALG com path de splice(), mas manteve a operação out-of-place. Scatterlists separados. Tudo seguro.
2017 — Aqui o bicho pegou. O commit 72548b093ee3 adicionou uma otimização de operação in-place. A ideia era simples: por que manter dois scatterlists separados se podemos usar um só? O código passou a fazer req->src = req->dst, combinando tudo em um único scatterlist.
O problema? Quando dados chegam via splice(), as páginas do scatterlist de destino são referências diretas à page cache do arquivo-alvo. E o authencesn faz uma escrita de 4 bytes nesse scatterlist como parte do processamento criptográfico.
Em código simplificado, a sequência fatal é:
// authencesn rearranges AAD bytes using destination as scratch
scatterwalk_map_and_copy(tmp, dst, 0, 8, 0); // lê AAD
scatterwalk_map_and_copy(tmp, dst, 4, 4, 1); // sobrescreve dst[4..7]
scatterwalk_map_and_copy(tmp+1, dst, assoclen+cryptlen, 4, 1); // BOOM
A terceira escrita — dst[assoclen + cryptlen] — cruza a fronteira do buffer de output e atinge a page cache do arquivo-alvo. E o authencesn nunca restaura os bytes originais. A escrita é permanente.
Por que isso é diferente do Dirty Cow e do Dirty Pipe
| Característica | Dirty Cow (2016) | Dirty Pipe (2022) | Copy Fail (2026) |
|---|---|---|---|
| Tipo de bug | Race condition | Inicialização incorreta de pipe flags | Falha de lógica no crypto path |
| Precisa de race? | Sim | Não | Não |
| Precisa de offsets? | Sim | Parcialmente | Não |
| Determinístico | Não | Sim | Sim |
| Tamanho do exploit | ~2KB+ | ~1KB | 732 bytes |
| Escrita controlada | Parcial | Parcial | Total (4 bytes, offset e valor controlados) |
| Detecção por HIDS | Sim | Sim | Não (page cache, disco inalterado) |
Essa última linha é a que tira o sono. O Copy Fail corrompe a page cache — a cópia em memória do arquivo — mas nunca marca a página como “dirty” para writeback. O arquivo no disco permanece intacto. Ferramentas de integridade como AIDE, Tripwire ou OSSEC que comparam checksums no disco não vão detectar nada.
O exploit de 732 bytes: passo a passo
O atacante controla três variáveis:
- Arquivo-alvo: qualquer arquivo legível pelo usuário corrente
- Offset: determinado pelos parâmetros de splice offset, splice length e assoclen
- Valor: os 4 bytes escritos derivam das posições 4-7 do AAD, construído via
sendmsg()
O ataque em si é assustadoramente simples:
import socket
# Step 1: Abre socket AF_ALG — sem privilégios
a = socket.socket(38, 5, 0) # AF_ALG, SOCK_SEQPACKET
a.bind(("aead", "authencesn(hmac(sha256),cbc(aes))"))
# Step 2: Configura a chave e parâmetros
# ... (setup do algoritmo AEAD)
# Step 3: sendmsg() com AAD contendo o payload nos bytes 4-7
# Step 4: splice() do arquivo-alvo (ex: /usr/bin/su)
# Step 5: recv() dispara a operação de decriptação
# authencesn escreve seqno_lo na page cache do arquivo
# A operação falha (ciphertext fabricado), mas a escrita persiste
Para cada chunk de 4 bytes de shellcode, o atacante repete o ciclo sendmsg + splice + recv. O HMAC falha porque o ciphertext é fabricado, recvmsg() retorna erro, mas a escrita na page cache já aconteceu.
No final, o atacante executa execve("/usr/bin/su"). Como o su é setuid-root, o kernel carrega o binário da page cache corrompida, e o shellcode injetado roda como UID 0.
Root. Em qualquer distro. Sem precisar de nada além de um terminal e Python.
Quem está vulnerável
A resposta curta? Basicamente todo mundo que roda Linux e não atualizou o kernel nos últimos dias.
O disclosure confirmou exploits funcionando em:
- Ubuntu 24.04 LTS (kernel 6.17.0-1007-aws)
- Amazon Linux 2023 (kernel 6.18.8-9.213.amzn2023)
- RHEL 10.1 (kernel 6.12.0-124.45.1.el10_1)
- SUSE 16 (kernel 6.12.0-160000.9-default)
O mesmo script Python de 732 bytes funciona em todas, sem modificação. Nada de compilar exploit para cada distro, nada de ajustar offsets.
Ambientes mais críticos:
- Cloud multi-tenant (EC2, GCP, Azure) — um container ou VM comprometida dá root no host
- CI/CD runners — código não confiável rodando em pipelines pode escalar privilégios
- Servidores compartilhados — hosting, universidades, qualquer ambiente com múltiplos usuários
A furtividade que assusta: por que ninguém detecta
Vou repetir porque vale: o Copy Fail não altera o arquivo no disco. Ele corrompe apenas a cópia em memória (page cache). Isso significa que:
sha256sum /usr/bin/suretorna o hash correto (lê do disco)cat /usr/bin/su | sha256sumpode retornar o hash corrompido (lê da page cache)- Ferramentas como AIDE, Tripwire e OSSEC que fazem verificação periódica de integridade não vão acusar nada
- Reboots “limpam” a corrupção porque a page cache é descartada e recarregada do disco
Isso cria um cenário perverso para incident response. Um atacante pode obter root, fazer o que quiser, e depois reiniciar o serviço afetado. A page cache é recarregada do disco limpo, e qualquer evidência forense baseada em integridade de arquivos desaparece.
Em ambientes de cloud, a situação é ainda pior. Containers compartilham o kernel do host. Se um processo dentro de um container sem privilégios executa o exploit, ele ganha root no host — não só dentro do container. Kubernetes, Docker, LXC — todos afetados da mesma forma.
Como o bug foi encontrado
Aqui tem um detalhe interessante: a vulnerabilidade foi identificada com assistência de IA. Segundo o disclosure, pesquisadores da Xint Code usaram modelos de linguagem guiados por contexto específico — focando na interação entre splice() e scatterlists criptográficos — e o scan identificou o bug em aproximadamente uma hora.
Isso levanta uma questão que a comunidade de segurança vai mastigar por meses: se uma IA encontrou esse bug em uma hora, quantos outros bugs similares existem esperando para serem encontrados da mesma forma? O kernel Linux tem milhões de linhas de código e interações complexas entre subsistemas que humanos simplesmente não conseguem auditar na mesma velocidade.
Já vimos essa tendência se acelerando. O Claude encontrou um bug de 23 anos no Linux no início de abril, e a DARPA financiou projetos de IA para bug hunting com milhões de dólares. O Copy Fail é mais um sinal de que a era da auditoria manual de segurança está chegando ao fim.
O fix é simples (e meio óbvio)
O patch (commit a664bf3d603d) reverteu a otimização de 2017. Em vez de operação in-place, o kernel volta a usar scatterlists separados:
Antes:
req->src = req->dst; // combined scatterlist, page cache pages writable
Depois:
req->src = sgl->src; // TX SGL (input only)
req->dst = sgl->dst; // RX SGL (user's buffer, no page cache pages)
Páginas da page cache ficam apenas no scatterlist de origem (leitura), nunca no de destino (escrita). A otimização de 2017 se foi — e com ela, o vetor de ataque.
O que fazer agora
Se você administra servidores Linux — e se está lendo isso, provavelmente administra — aqui vai o plano de ação:
Passo 1: Atualize o kernel
Verifique se sua distro já lançou o patch:
# Ubuntu/Debian
sudo apt update && sudo apt upgrade linux-image-$(uname -r)
# RHEL/CentOS/Fedora
sudo dnf update kernel
# SUSE
sudo zypper update kernel-default
# Após atualizar, reinicie
sudo reboot
Passo 2: Mitigação imediata (se não pode reiniciar agora)
Desabilite o módulo vulnerável:
# Blacklist do módulo algif_aead
echo "install algif_aead /bin/false" | sudo tee /etc/modprobe.d/disable-algif-aead.conf
# Se o módulo já está carregado, remova
sudo rmmod algif_aead 2>/dev/null
# Alternativa: bloqueie AF_ALG via seccomp
# (requer configuração específica por aplicação)
Passo 3: Verifique se o módulo está carregado
lsmod | grep algif_aead
Se não retornar nada, o módulo não está carregado e a superfície de ataque é menor (mas não zero — qualquer processo pode carregar o módulo via socket).
Passo 4: Monitore
Ferramentas tradicionais de integridade de arquivos não detectam corrupção de page cache. Se você precisa de garantia, considere:
- Reiniciar serviços críticos (força reload da page cache do disco limpo)
- Verificar binários setuid comparando com pacotes da distro:
rpm -Voudebsums - Monitorar logs de
AF_ALGsocket creation via auditd
# Auditd rule para detectar uso de AF_ALG
sudo auditctl -a always,exit -F arch=b64 -S socket -F a0=38 -k af_alg_usage
Timeline do disclosure
O processo de responsible disclosure seguiu o protocolo padrão do kernel:
| Data | Evento |
|---|---|
| 23/03/2026 | Vulnerabilidade reportada ao Linux kernel security team |
| 24/03/2026 | Acknowledgment inicial |
| 25/03/2026 | Patches propostos e revisados |
| 01/04/2026 | Patches commitados no mainline |
| 22/04/2026 | CVE-2026-31431 atribuído |
| 29/04/2026 | Disclosure público |
Foram 37 dias entre o report e o disclosure público. As distros tiveram quase um mês para preparar patches — e a maioria já tem atualizações disponíveis. Se você ainda não aplicou, o exploit já é público e qualquer pessoa pode reproduzi-lo.
O contexto maior
O Copy Fail é o terceiro grande exploit de page cache/pipe do Linux em quatro anos, depois do Dirty Pipe (2022) e do Wall Escape (2024). E cada um é mais elegante que o anterior.
A comunidade no Hacker News já está debatendo se o modelo de segurança do kernel Linux precisa de uma revisão fundamental. O AF_ALG em particular é um subsistema que expõe operações criptográficas complexas para userspace sem privilégios — uma superfície de ataque enorme que poucos olhos realmente auditam. Quantos outros subsistemas obscuros do kernel têm problemas similares? O io_uring já deu dor de cabeça suficiente. O eBPF vive sendo alvo. E agora o AF_ALG entra na lista.
O CVSS score de 7.8 pode parecer “alto” mas não “crítico” — até você perceber que a exploração é trivial, determinística, e funciona em qualquer distro. Na prática, o impacto real é muito maior do que o score sugere.
Enquanto isso, a IA está acelerando a descoberta de vulnerabilidades em ritmo exponencial. Se o Copy Fail foi encontrado em uma hora com assistência de modelos de linguagem, estamos entrando numa era onde o “security through obscurity” dos subsistemas menos populares do kernel simplesmente não funciona mais.
A corrida agora é entre pesquisadores e atacantes — ambos com acesso às mesmas ferramentas de IA. E o kernel Linux, com seus 30+ milhões de linhas de código e décadas de otimizações acumuladas, é o campo de batalha perfeito.
Fonte de inspiração: Copy Fail — CVE-2026-31431 | Xint Code Blog













