Dirty Frag: uma nova vulnerabilidade de escalonamento de privilégios de cópia zero do kernel Linux
Dirty Frag: Uma cadeia de vulnerabilidades no caminho de cópia zero do kernel Linux que envenena gravações de cache de página, encadeando as vulnerabilidades xfrm-ESP e RxRPC. Afeta quase todas as distribuições convencionais desde 2017 e permite o escalonamento de privilégios sem senha para root.
Aqui vamos nós de novo
Para ser honesto, nunca pensei que escreveria outro post sobre escalonamento de privilégios do kernel tão cedo.
Faz apenas oito dias desde o artigo Copy Fail. Oito dias! A lista negra algif_aead do Copy Fail mal tinha sido digitada no terminal, o patch nem estava quente e então—Dirty Frag caiu.
O que é ainda mais absurdo é que as mitigações do Copy Fail são completamente ineficazes contra Dirty Frag. Desta vez, o ataque tem como alvo subsistemas de kernel totalmente diferentes – os caminhos de criptografia xfrm-ESP e RxRPC – portanto, desabilitar algif_aead ou não não faz absolutamente nenhuma diferença.
Dirty Pipe (2022), Copy Fail (2026.04), Dirty Frag (2026.05)… Sempre que “afeta quase todas as distribuições desde 2017.” Você sabe o que isso significa? Isso significa que durante quase a última década, qualquer pessoa que fez login em qualquer conta sem privilégios em seu sistema teve a chance de se tornar root silenciosamente.
Mas pensando bem, isso é inteiramente culpa dos desenvolvedores do kernel? Não necessariamente.
O crescimento explosivo de ferramentas de auditoria de código assistidas por IA nos últimos anos permite que os pesquisadores de segurança verifiquem vulnerabilidades que estão à espreita há quase uma década em poucas horas. Bugs que antes exigiam revisão manual linha por linha agora são eliminados em lotes pela IA. Copy Fail foi localizado pela ferramenta AI Xint Code em uma hora. Embora o Dirty Frag tenha surgido da auditoria manual do pesquisador coreano Hyunwoo Kim, os caminhos de código que ele explora pertencem à mesma família do Copy Fail – gravações de cache de páginas no caminho de cópia zero – indicando que esse tipo de falha de design está longe de ser um caso isolado. Melhores ferramentas, maior eficiência e, naturalmente, mais vulnerabilidades são “descobertas”.
O que é ainda mais perturbador é o processo de divulgação desta vez. O pesquisador originalmente enviou detalhes da vulnerabilidade à equipe de segurança do kernel com um embargo de 5 dias acordado para dar tempo às distribuições para corrigir. Mas no mesmo dia, um terceiro não relacionado publicou diretamente os detalhes completos e a exploração da vulnerabilidade ESP(xfrm). Sem CVE, sem patch, mas o PoC estava disponível para todos. Esta não é uma divulgação responsável – é apunhalar cada usuário Linux pelas costas. A janela de remendo foi destruída e todos foram forçados a correr nus.
Tudo bem, acabou o discurso. Vamos dar uma olhada séria no que se trata essa vulnerabilidade.
Linha do tempo
| Data | Evento |
|---|---|
| 2017-01 | Vulnerabilidade xfrm-ESP introduzida com commit cac2661c53f3 (escondida por 9 anos) |
| 2023-06 | Vulnerabilidade RxRPC introduzida com commit 2dc334f1a63a |
| 29/04/2026 | O pesquisador coreano Hyunwoo Kim (@v4bel) relata vulnerabilidade RxRPC e exploração completa para security@kernel.org |
| 07/05/2026 | Detalhes de vulnerabilidade enviados à lista de discussão linux-distros com embargo de 5 dias acordado |
| 07/05/2026 | No mesmo dia, terceiros divulgam publicamente detalhes de vulnerabilidade e exploração do ESP(xfrm), embargo quebrado imediatamente |
| 07/05/2026 | Após consulta aos mantenedores da distribuição, a documentação completa do Dirty Frag foi divulgada publicamente. Neste ponto sem CVE, sem patch oficial |
| 08/05/2026 | No momento em que este artigo foi escrito, as principais distribuições ainda estavam aguardando a fusão do patch upstream |
Análise de Impacto
| Métrica | Detalhes |
|---|---|
| CVE | Nenhum ainda (NVD não teve tempo de atribuir antes do embargo quebrar) |
| Tipo de vulnerabilidade | Falha lógica determinística, não uma condição de corrida |
| Taxa de sucesso de exploração | 100%, sucesso garantido na primeira execução |
| Intervalo afetado | Quase todas as principais distribuições Linux desde 2017 (em maio de 2026, o kernel 7.0.3 mais recente também foi afetado) |
| Método de Exploração | Carga útil de 192 bytes, montando um ELF de shell raiz por meio de 48 gravações de 4 bytes |
| Pegada de disco | Nenhuma modificação persistente — apenas polui o cache da página na memória, ignorando o inotify; restaurado na reinicialização |
| Ignora a mitigação de falhas de cópia | A desativação de algif_aead do Copy Fail é completamente ineficaz, pois ataca diferentes subsistemas |
Comparação com vulnerabilidades históricas de LPE do kernel:| Recurso | Vaca Suja (2016) | Tubo Sujo (2022) | Falha na cópia (2026) | Fragmento Sujo (2026) | | — | — | — | — | — | | Condição de corrida | Obrigatório | Não obrigatório | Não obrigatório | Não obrigatório | | Faixa afetada | Versões específicas | 5,8+ | Todas as distros convencionais desde 2017+ | Todas as distros principais desde 2017+ | | Explorar a complexidade do código | Complexo | Complexo | 10 linhas Python | Programa C de arquivo único | | Pegada em disco | Sim | Sim | Não | Não | | Status do patch | Fixo | Fixo | Fixo | Nenhum patch oficial ainda |
Distribuições afetadas confirmadas:
| Distribuição | Versão testada do kernel |
|---|---|
| Ubuntu 24.04.4 | 6.17.0-23-genérico |
| RHEL 10.1 | 6.12.0-124.49.1 |
| Fluxo CentOS 10 | 6.12.0-224 |
| AlmaLinux 10 | 6.12.0-124.52.3 |
| Fedora 44 | 19.6.14-300 |
| OpenSUSE Tumbleweed | 7.0.2-1 |
| Arco Linux | 7.0.3 |
Do 6.12 ao 7.0, do Ubuntu ao Arch —cobertura total da plataforma. Sim, praticamente qualquer distribuição convencional que você instalou provavelmente será afetada.
Princípios Técnicos: Por que “Dirty Frag”?
O núcleo em uma frase
splice() implanta uma referência de cache de página de arquivo somente leitura no slot de frag do buffer de envio de rede (skb) → o kernel receptor executa operações criptográficas no local no frag (criptografia no local, src == dst apontando para a mesma memória) → o que deveria ter sido uma operação de descriptografia no texto cifrado se torna uma gravação primitiva STORE direta no cache de página somente leitura → substituindo a máquina de su código com um ELF de shell raiz.
“Dirty” refere-se a poluir o cache da página, “Frag” refere-se à exploração do mecanismo de fragmento skb (socket buffer). Juntos—Dirty Frag.
Caminho de cópia zero skb Frag Pollution
Esta parte é fundamental para entender toda a vulnerabilidade, então vamos expandi-la.
Normalmente, quando você grava dados em um soquete, o kernel copia os dados do espaço do usuário para seu skb. Mas splice() segue o caminho cópia zero - ele coloca diretamente o ponteiro para a página de cache da página do arquivo (page struct + offset) no array frag do skb sem copiar os dados em si:
struct skb_shared_info { struct sk_buff *frag_list; // frag linked list skb_frag_t frags[MAX_SKB_FRAGS]; // frag array, each is {page, offset, size} // ...};O ponto principal aqui: o page passado para splice() é o seu arquivo (por exemplo, /usr/bin/su) página de cache de página na memória — você só tem permissões de leitura, mas uma referência a esta página já foi inserida no skb da pilha de protocolo de rede.
Em seguida, depende se a pilha de protocolo de rede receptora “coça as mãos” e grava nesta página.
Vulnerabilidade 1: Gravação de cache de página xfrm-ESP
A primeira vulnerabilidade está no caminho de descriptografia IPsec ESP (Encapsulating Security Payload).
A função esp_input() é usada para descriptografar dados de texto cifrado. Normalmente, se a região de dados do skb for compartilhada com um frag, o kernel deve primeiro chamar skb_cow_data() (Copy-on-Write) para copiar a página compartilhada antes de operar nela. No entanto, existe um caminho de código em esp_input() que ignora COW:
static int esp_input(struct xfrm_state *x, struct sk_buff *skb){ if (!skb_cloned(skb)) { if (!skb_is_nonlinear(skb)) { // [1] Linear skb: only head data, no frag, safe nfrags = 1; goto skip_cow; } else if (!skb_has_frag_list(skb)) { // [2] Has frag, but no frag_list → directly skips cow! nfrags = skb_shinfo(skb)->nr_frags; nfrags++; goto skip_cow; // The bomb is here } } // Normal path: copy data, safe err = skb_cow_data(skb, 0, &trailer);}Quando o skb é não linear (possui fragmentos que contêm o cache da página passado pela emenda), mas frag_list está vazio, o código salta diretamente para skip_cow. Em seguida, o crypto_authenc_esn_decrypt() subsequente executa a descriptografia AEAD no local – src e dst apontam para a mesma lista de dispersão, que é a página de cache de página implantada pelo invasor.
Durante o processo de descriptografia, há uma linha de código particularmente crítica:
// Move the high 4 bytes of sequence number to the end of dst SGLscatterwalk_map_and_copy(tmp + 1, dst, assoclen + cryptlen, 4, 1);Esta linha grava 4 bytes em dst (sua página de cache de página su) no deslocamento assoclen + cryptlen. O valor de tmp + 1 vem dos 32 bits superiores do número de sequência do cabeçalho ESP – algo que o invasor controla totalmente por meio de XFRMA_REPLAY_ESN_VAL.seq_hi ao registrar a XFRM SA (Security Association).
Portanto, o invasor controla simultaneamente:
- Onde escrever (deslocamento do arquivo, posicionado ajustando o comprimento da carga útil)
- Qual valor escrever (4 bytes, especificado via
seq_hi)
Ao registrar 48 SAs XFRM diferentes, cada uma com seu seq_hi armazenando um fragmento de 4 bytes do ELF e fazendo um loop 48 vezes, um ELF de shell raiz completo é montado no cache de página do su.
No entanto, esta vulnerabilidade tem uma limitação: o registro de SAs XFRM requer privilégios CAP_NET_ADMIN. Os invasores podem obter isso criando namespaces de usuário (unshare(CLONE_NEWUSER | CLONE_NEWNET)) – mas o AppArmor do Ubuntu evita que usuários sem privilégios criem namespaces de rede.
É por isso que uma segunda vulnerabilidade é necessária.
Vulnerabilidade 2: Gravação de cache de página RxRPC
A segunda vulnerabilidade está no caminho de descriptografia da autenticação Kerberos do protocolo RxRPC.A função rxkad_verify_packet_1() executa a descriptografia pcbc(fcrypt) local nos primeiros 8 bytes dos pacotes de dados recebidos:
skcipher_request_set_crypt(req, sg, sg, 8, iv.x);// ^^ ^^// src==dst → in-place operation!ret = crypto_skcipher_decrypt(req); // 8-byte write happens hereskb_to_sgvec() converte diretamente o frag do skb (que contém a página de cache da página inserida pelo invasor) em uma lista de dispersão, com src e dst sendo o mesmo sg. Portanto, a operação de descriptografia grava diretamente o “resultado da descriptografia” de 8 bytes de volta naquela página de cache de página somente leitura.
Comparado ao xfrm-ESP:
| Recurso | xfrm-ESP | RxRPC |
|---|---|---|
| Tamanho da gravação | 4 bytes | 8 bytes |
| Controle de valor | Controlo direto (seq_hi) |
Indireto (requer força bruta da chave fcrypt) |
| Privilégio necessário | Espaço para nome do usuário | Não é necessário privilégio |
| Hora da introdução | 2017-01 | 2023-06 |
Os valores escritos através do caminho RxRPC não podem ser controlados diretamente – eles são o resultado de fcrypt_decrypt(C, K). O invasor precisa primeiro registrar uma chave K por meio de add_key("rxrpc", ...) e, em seguida, usar força bruta no espaço do usuário para encontrar o K que produz o texto simples de 8 bytes alvo. Felizmente, fcrypt é uma chave de 56 bits e uma cifra de bloco de 8 bytes dedicada ao Andrew File System, portanto, a força bruta não é um grande problema.
O ponto mais crítico: o caminho RxRPC não requer absolutamente nenhum privilégio. Não há necessidade de criar namespaces de usuário, nem de namespaces de rede, nem de CAP_NET_ADMIN. E o Ubuntu carrega o módulo rxrpc.ko por padrão.
Lógica de encadeamento
As duas vulnerabilidades se complementam, proporcionando cobertura total:
| Cenário | Vulnerabilidade usada | Razão |
|---|---|---|
| Ubuntu (AppArmor bloqueia namespaces) | RxRPC | rxrpc.ko carregado por padrão, nenhum privilégio necessário |
| RHEL/Fedora/openSUSE | xfrm-ESP | Namespaces disponíveis, ESP escreve com precisão controlável |
| Outras distribuições | xfrm-ESP ou RxRPC | Escolha com base no carregamento do módulo, pelo menos um caminho disponível |
Isso é o que torna o Dirty Frag assustador —não importa como você o configure, sempre há um caminho para o root.
Análise PoC
A exploração completa é de código aberto em github.com/V4bel/dirtyfrag. Compilar e executar requer apenas uma linha:
git clone https://github.com/V4bel/dirtyfrag.gitcd dirtyfrag && gcc -O0 -Wall -o exp exp.c -lutil && ./expA ideia central não é complicada:
- Prepare um ELF mínimo de 192 bytes - um shell root que executa com escalonamento de privilégios
- Divida esses 192 bytes em 48 pedaços de 4 bytes (se estiver usando o caminho xfrm-ESP)
- Registre um XFRM SA para cada bloco de 4 bytes, com seu
seq_hidefinido para o valor desse bloco - Cada vez, use
splice()para enviar o cache da página desupara o skb, acionando uma gravação no local - Faça um loop 48 vezes e a região de cache da página de
su(primeiros 192 bytes) é completamente substituída pelo ELF do shell raiz execve("/usr/bin/su")→ shell raiz
Todo o processo nunca afeta os arquivos do disco. O /usr/bin/su no disco permanece intacto, seu md5 ainda é o md5 original. Mas no cache de páginas do kernel, ele foi substituído secretamente.
Quando qualquer processo inicia execve em su, o kernel lê o cache da página – opa, ele executa o binário que você injetou. Raiz obtida.
Resposta de emergência: desative temporariamente módulos vulneráveis
Em 8 de maio de 2026, patches oficiais do kernel ainda não foram lançados. Até que os patches estejam disponíveis, a única mitigação temporária é descarregar e colocar na lista negra os três módulos vulneráveis.
Primeiro, confirme se o seu sistema foi afetado:
lsmod | grep -E 'esp4|esp6|rxrpc'Se houver alguma saída, você será afetado.
Execute os seguintes comandos imediatamente (não é necessário reinicializar):
sudo sh -c "printf 'install esp4 /bin/false\ninstall esp6 /bin/false\ninstall rxrpc /bin/false\n' > /etc/modprobe.d/dirtyfrag.conf"sudo rmmod esp4 esp6 rxrpc 2>/dev/nullVerifique:
lsmod | grep -E 'esp4|esp6|rxrpc'Importante: Se você suspeitar que o PoC já foi executado, você deve limpar o cache da página:
echo 3 | sudo tee /proc/sys/vm/drop_cachesSe você não fizer isso, mesmo depois de desabilitar os módulos, o cache da página poluída permanecerá na memória – a execução de su ainda fornecerá um shell de root.
Efeitos colaterais:
- Desativar
esp4/esp6interromperá os túneis VPN IPsec. Os usuários de desktop e a maioria dos servidores não são afetados, mas se você depende de VPN IPsec (como strongSwan, Libreswan), avalie primeiro o impacto. - Desativar
rxrpctem impacto mínimo, a menos que você esteja usando AFS (Andrew File System).
Corrida armamentista de vulnerabilidade acelerada por IA
A exposição do Dirty Frag nos força a pensar em uma questão mais profunda: Por que as vulnerabilidades LPE do kernel estão surgindo uma após a outra recentemente?
| Vulnerabilidade | Tempo de descoberta | Ferramenta principal | Do relatório ao público |
|---|---|---|---|
| Tubo Sujo | 2022 | Auditoria manual | Processo padrão |
| Falha na cópia | 2026-04 | Código Xint (AI) | Cerca de um mês |
| Fragmento Sujo | 2026-05 | Auditoria manual | 8 dias (embargo quebrado no mesmo dia) |
Por trás disso está o crescimento explosivo de ferramentas de auditoria de código assistidas por IA. Anteriormente, contando com a revisão humana linha por linha, uma vulnerabilidade que permanecesse sem ser descoberta por dez anos era normal. Agora a IA pode verificar um subsistema inteiro em poucas horas, retirando todos os possíveis caminhos de cópia zero, operações no local e referências compartilhadas. Melhores ferramentas, maior eficiência e, naturalmente, mais vulnerabilidades são “descobertas” – o kernel não piorou repentinamente, apenas dívidas antigas escondidas nos cantos estão sendo descobertas uma a uma pela IA.
O que é ainda mais alarmante é a mudança no ecossistema de divulgação. O embargo do Dirty Frag foi deliberadamente quebrado por terceiros, com detalhes de vulnerabilidade e PoC divulgados no mesmo dia. O que isto significa? Isso significa que desde o pesquisador relatando a vulnerabilidade a security@kernel.org até hackers em todo o mundo obtendo suas armas, apenas oito dias se passaram. A janela de patch desapareceu.
Podemos culpar a pessoa que quebrou o embargo por ser antiética. Mas a realidade é que isso só acontecerá cada vez mais. A IA torna a descoberta de vulnerabilidades mais rápida e a criação de armas também mais rápida. Nem sempre se pode contar com que todos cumpram os acordos de embargo.
E não se esqueça, a mesma família de vulnerabilidades ainda está sendo desenterrada:
| Vulnerabilidade | Subsistema | Estado |
|---|---|---|
| Falha na cópia | AF_ALG + autenticaçãosn | Fixo |
| Fragmento Sujo | xfrm-ESP + RxRPC | Sem patch |
| Falha na cópia 2 | ESP em UDP | Divulgado publicamente |
| Lista gratuita ZCRX | io_uring ZCRX | Divulgado publicamente |
Os princípios básicos dessas quatro vulnerabilidades são surpreendentemente semelhantes: splice() armazena referências de cache de página somente leitura em subsistemas de kernel, e os subsistemas gravam no local nos frags. O que eles expõem é na verdade a mesma classe de problema de design:
| Componente | Motivo da introdução | Efeito colateral |
|---|---|---|
splice() |
Cópia zero, otimização de desempenho | Referências de cache de página somente leitura enviadas para subsistemas de kernel |
AF_ALG |
Expor os recursos de criptografia do kernel | Usuários sem privilégios podem iniciar sessões criptográficas diretamente |
| xfrm-ESP | Aceleração IPsec | Descriptografia no local, usando páginas somente leitura como buffers de saída |
| RxRPC | Suporte ao protocolo de rede AFS | O mesmo que acima, nem precisa de privilégios de namespace |
Cada projeto, considerado individualmente, é uma otimização de desempenho razoável ou um requisito funcional. Mas reunidos, eles formam uma cadeia de vulnerabilidades onde qualquer usuário local pode se tornar root sem uma senha.
A menos que o kernel upstream reexamine completamente o paradigma de “operações no local em caminhos de cópia zero”, eu garanto a você—este não será o último.
Para usuários comuns, meu conselho é simples:
- Execute os comandos da lista negra acima agora. Altere-os novamente quando o patch oficial chegar.
- Monitore de perto as atualizações do kernel a partir do seu gerenciador de pacotes. Assim que uma versão corrigida estiver disponível, atualize e reinicie imediatamente.
- Regularmente
lsmod | greppara verificar se esses módulos foram carregados acidentalmente.
Referências
- Repositório GitHub PoC: https://github.com/V4bel/dirtyfrag
- Relatório LWN: https://lwn.net/Articles/1071719/
- Relatório Phoronix: https://www.phoronix.com/news/Dirty-Frag-Linux
- Análise Técnica Coreana (GeekNews): https://news.hada.io/topic?id=29275
- Site de divulgação de falha de cópia: https://copy.fail/
- Falha de cópia 2 (Electric Boogaloo): https://github.com/0xdeadbeefnetwork/Copy_Fail2-Electric_Boogaloo
Infográficos

Figura 1: Visão geral da vulnerabilidade Dirty Frag — como as referências de cache de página de cópia zero são exploradas por meio de frags skb