← voltar
CVE-2024-36971highsob ataqueCWE-416

net: fix __dst_negative_advice() race

71Vexday Risk Score

Priorize a correção. Ela está sob exploração confirmada pelo CISA e tem prova de conceito pública.

ssvc Actcvss 7.8epss 2.7%
da publicação à arma491 dias
Publicada no NVD10 de jun.
1ª PoC+491d
CISA KEV+58d
probabilidade de exploração
2.7%top 16% das CVEs
exploração observada
simCISA + VulnCheck
1 exploit(s) público(s)
Ação exigida pela CISAprazo federal: 2024-08-28

Apply mitigations per vendor instructions or discontinue use of the product if mitigations are unavailable.

Resumo

Use-after-free no subsistema de rede do kernel Linux, na função __dst_negative_advice(), que é chamada quando o kernel decide que a rota (dst_entry) associada a um socket está degradada e precisa ser descartada. A ordem errada de operações RCU permite que outra thread, lendo concorrentemente o cache de rota do socket, obtenha um ponteiro para uma estrutura já liberada. A falha exige execução local (AV:L) com privilégio baixo para gerar a concorrência necessária — não é explorável remotamente sem já ter presença na máquina — mas está confirmada em exploração ativa (catálogo KEV da CISA) e foi reportada por um pesquisador da Google associado a investigações de spyware, o que eleva sua relevância para escalonamento de privilégios local.

Detalhamento técnico

O kernel mantém em cada struct sock um ponteiro sk_dst_cache para a rota (dst_entry) usada para rotear pacotes daquele socket, protegido por regras RCU: para trocar ou remover esse ponteiro com segurança, é preciso primeiro zerar/reatribuir sk->sk_dst_cache via rcu_assign_pointer() e só depois chamar dst_release() no dst_entry antigo. Isso garante que um leitor concorrente sob rcu_read_lock() nunca veja um ponteiro válido para uma estrutura cujo refcount já foi decrementado a zero.

A implementação de __dst_negative_advice() violava essa ordem: os callbacks de negative_advice (ipv4_negative_advice, ip6_negative_advice, xfrm_negative_advice) chamavam ip_rt_put()/dst_release() sobre o dst antigo dentro do próprio callback e retornavam um novo ponteiro (ou NULL) para a função central, que só então fazia rcu_assign_pointer(sk->sk_dst_cache, ndst). Ou seja, a liberação acontecia antes da atualização do ponteiro visível a outras threads — o inverso do que sk_dst_reset() (a função irmã, que já implementava a ordem correta) fazia. Isso é uma condição de corrida clássica entre um caminho de escrita (invalidação de rota) e um caminho de leitura (uso do dst em outra thread do mesmo socket), classificável como CWE-416 (Use-After-Free) com componente de CWE-362 (race condition).

O bug em si é antigo — existe desde a implementação original do mecanismo negative_advice — mas, segundo o commit de correção, 'se tornou visível' após o commit a87cb3e48ee8 ('net: Facility to report route quality of connected sockets'), que passou a acionar esse caminho de código com sockets UDP em cenários que antes não o exercitavam na prática.

A correção reestrutura a interface: o ponteiro de função dst_ops->negative_advice deixa de retornar um novo dst_entry* e passa a receber o struct sock* diretamente, chamando sk_dst_reset(sk) internamente em cada implementação (IPv4, IPv6, xfrm) sempre que decide invalidar a rota. Isso centraliza a ordem correta de RCU (zera o ponteiro antes de liberar) em um único ponto reaproveitado por todos os callbacks, eliminando a duplicação de lógica que causava a inconsistência.

Como é explorada

O gatilho para __dst_negative_advice() ocorre quando o kernel marca uma rota como degradada — por exemplo, rota obsoleta, marcada como redirecionada (RTCF_REDIRECTED) por um ICMP redirect, ou com cache expirado. Para explorar a race, um atacante precisa de um socket UDP local sob seu controle e de duas operações concorrentes: uma thread que force a invalidação da rota do socket (fazendo o kernel entrar no caminho negative_advice) enquanto outra thread, no mesmo processo ou em thread relacionada, acessa o dst_cache do mesmo socket (por exemplo, enviando dados). A janela de corrida é estreita e depende de timing, mas é uma primitiva clássica de UAF em kernel — controlável com técnicas de heap grooming para tentar realocar a memória liberada com dados controlados pelo atacante, obtendo potencial escrita/leitura arbitrária ou escalonamento de privilégios a partir de um processo sem privilégios.

O vetor é estritamente local: o CVSS (AV:L/AC:L/PR:L/UI:N) reflete que é preciso já ter capacidade de executar código no host com privilégio baixo (criar sockets, gerar tráfego, eventualmente induzir a invalidação de rota), sem depender de interação do usuário. Não há componente de rede remota na exploração — um atacante remoto não consegue disparar a race sem já ter um processo executando na máquina vítima.

A CVE está no catálogo KEV da CISA, indicando exploração confirmada em campo, e foi reportada por um pesquisador da Google (Clement Lecigne) historicamente associado à identificação de bugs usados em cadeias de exploração de spyware/comercial. Isso sugere que a falha foi encontrada como parte de uma cadeia de escalonamento de privilégios local, não como vulnerabilidade explorada isoladamente por scanners em massa — consistente com o EPSS baixo (0.027), que mede probabilidade de exploração oportunista de internet e não captura bem ataques direcionados de escalonamento local.

Versões

Afetadas
Kernels Linux que contêm o mecanismo negative_advice de dst_entry com a ordem incorreta de operações RCU em __dst_negative_advice() — presente desde antes do commit a87cb3e48ee8 ('net: Facility to report route quality of connected sockets'), que tornou o caminho de código exercitável de forma prática com sockets UDP. As fontes não especificam uma faixa numérica exata de versões (major.minor) afetadas; recomenda-se verificar se o kernel em uso já incorpora o commit de correção listado abaixo.
Corrigidas em
Corrigido pelo commit upstream 92f1655aa2b2294d0b49925f3b875a634bd3b59e, com backports publicados para múltiplos ramos da árvore estável do kernel Linux (hashes de backport listados nas referências desta página). Verifique o changelog do kernel específico da distribuição para confirmar a versão exata que incorpora o patch.

Como se proteger

A correção definitiva é atualizar o kernel para uma versão que inclua o commit upstream 92f1655aa2b2294d0b49925f3b875a634bd3b59e ('net: fix __dst_negative_advice() race'). Esse commit foi retroportado para múltiplos ramos estáveis do kernel (visíveis nos hashes de backport listados nas referências); a versão exata de destino depende da distribuição e do ramo LTS em uso — confira o changelog do kernel da sua distribuição para confirmar se o patch já foi incorporado, em vez de assumir por número de versão.

Não existe flag de configuração, módulo a desabilitar ou parâmetro de sysctl que mitigue a falha sem o patch — o código afetado é central ao caminho de roteamento IPv4/IPv6/xfrm de qualquer socket UDP (e potencialmente outros tipos que usam negative_advice), e não pode ser contornado por WAF ou configuração de aplicação, já que é uma falha interna ao kernel. O único controle compensatório real é reduzir a superfície de exposição local: evitar execução de código não confiável (contêineres, VMs, usuários múltiplos) em kernels sem o patch, já que a exploração exige presença local com privilégio baixo.

Mitigações de hardening de kernel como KASLR, SMEP/SMAP ou KASAN não impedem a exploração — no máximo, KASAN ajuda a detectar o UAF em ambientes de teste/debug, mas não é viável em produção pela sobrecarga de desempenho. Não há paliativo de runtime equivalente ao patch; a única ação eficaz é a atualização do kernel.

Como detectar

Não há assinatura de rede ou log de aplicação confiável para detectar tentativas de exploração — a falha é uma condição de corrida interna ao kernel, sem tráfego de rede distintivo. Em ambientes com KASAN habilitado (tipicamente apenas em builds de debug/teste, não produção), a exploração ou o acionamento acidental da race pode gerar relatórios de use-after-free apontando para net/ipv4/route.c, net/ipv6/route.c ou net/xfrm/xfrm_policy.c envolvendo dst_entry. Em produção, o sintoma mais provável de exploração falha ou tentativa é instabilidade do kernel (panics/oops) associada ao subsistema de roteamento sob carga de sockets UDP — sinal indireto e não conclusivo, sem correlação direta a um atacante específico.

Pesquisado e redigido com IA a partir do advisory do fornecedor e de análises públicas, com as fontes acima. Confira sempre a versão corrigida no advisory oficial antes de agir.
In the Linux kernel, the following vulnerability has been resolved: net: fix __dst_negative_advice() race __dst_negative_advice() does not enforce proper RCU rules when sk->dst_cache must be cleared, leading to possible UAF. RCU rules are that we must first clear sk->sk_dst_cache, then call dst_release(old_dst). Note that sk_dst_reset(sk) is implementing this protocol correctly, while __dst_negative_advice() uses the wrong order. Given that ip6_negative_advice() has special logic against RTF_CACHE, this means each of the three ->negative_advice() existing methods must perform the sk_dst_reset() themselves. Note the check against NULL dst is centralized in __dst_negative_advice(), there is no need to duplicate it in various callbacks. Many thanks to Clement Lecigne for tracking this issue. This old bug became visible after the blamed commit, using UDP sockets.
CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H
Produtos afetados
Linux · Linux
PoCs públicas encontradas1
githubgithub.com/M4G1XX/CVE-2024-369711
⚠ Recursos públicos, para você avaliar a exposição de sistemas que controla ou está autorizado a testar. Teste apenas com autorização.