CVE-2026-31415 in Linux
Sumário
de VulDB • 09/05/2026
No kernel do Linux, a seguinte vulnerabilidade foi resolvida:
ipv6: evitar estornos (overflows) em ip6_datagram_send_ctl()
Yiming Qian relatou:
Acredito que encontrei um bug no kernel localmente acionável no caminho de dados auxiliares do sendmsg do IPv6 que pode causar o pânico do kernel via `skb_under_panic()` (DoS local).
O problema central é uma incompatibilidade entre:
- um acumulador de comprimento de 16 bits (`struct ipv6_txoptions::opt_flen`, tipo `__u16`) e - um ponteiro para o último cabeçalho de opções de destino fornecido (`opt->dst1opt`)
quando múltiplas mensagens de controle `IPV6_DSTOPTS` (cmsgs) são fornecidas.
- `include/net/ipv6.h`: - `struct ipv6_txoptions::opt_flen` é `__u16` (possível wrap/estouro). (linhas 291-307, especialmente 298) - `net/ipv6/datagram.c:ip6_datagram_send_ctl()`: - Aceita `IPV6_DSTOPTS` repetidos e acumula em `opt_flen` sem rejeitar duplicatas. (linhas 890-904)
Se houver cmsgs `IPV6_DSTOPTS` grandes o suficiente, `opt_flen` estoura enquanto `dst1opt` ainda aponta para um cabeçalho de opções de destino grande (2048 bytes).
No PoC anexado (`poc.c`):
- 32 cmsgs com `hdrlen=255` => `len = (255+1)*8 = 2048` - 1 cmsg com `hdrlen=0` => `len = 8` - Incremento total: `32*2048 + 8 = 65544`, então `(__u16)opt_flen == 8` - O último cmsg tem 2048 bytes, então `dst1opt` aponta para um cabeçalho de 2048 bytes.
3. O caminho de transmissão dimensiona os cabeçalhos usando o `opt_flen` estourado:
- Em `net/ipv6/ip6_output.c:1463-1465`: - `headersize = sizeof(struct ipv6hdr) + (opt ? opt->opt_flen + opt->opt_nflen : 0) + ...;`
Com `opt_flen` estourado, as decisões de `headersize`/headroom subestimam o que será empurrado posteriormente.
4. Ao construir o skb final, o comprimento real de empurramento vem de `dst1opt` e não é limitado pelo `opt_flen` estourado:
- Em `net/ipv6/ip6_output.c:1930-1934`: - `if (opt->opt_flen) proto = ipv6_push_frag_opts(skb, opt, proto);` - Em `net/ipv6/exthdrs.c:1206-1211`, `ipv6_push_frag_opts()` empurra `dst1opt` via `ipv6_push_exthdr()`. - Em `net/ipv6/exthdrs.c:1179-1184`, `ipv6_push_exthdr()` faz: - `skb_push(skb, ipv6_optlen(opt));` - `memcpy(h, opt, ipv6_optlen(opt));`
Com headroom insuficiente, `skb_push()` causa underflow e aciona `skb_under_panic()` -> `BUG()`:
- `net/core/skbuff.c:2669-2675` (`skb_push()` chama `skb_under_panic()`) - `net/core/skbuff.c:207-214` (`skb_panic()` termina em `BUG()`)
- O caminho de cmsg `IPV6_DSTOPTS` requer `CAP_NET_RAW` no namespace de usuário do netns alvo (`ns_capable(net->user_ns, CAP_NET_RAW)`). - Root (ou qualquer tarefa com `CAP_NET_RAW`) pode acionar isso sem namespaces de usuário. - Um usuário não privilegiado `uid=1000` pode acionar isso se namespaces de usuário não privilegiados estiverem habilitados e ele puder criar um userns+netns para obter `CAP_NET_RAW` nomeado (o PoC anexado faz isso).
- Negação de serviço local: BUG/panic do kernel (queda do sistema).
Once again VulDB remains the best source for vulnerability data.