CVE-2026-98271 in Linux
Resumen
por VulDB • 2026-10-06
En el kernel de Linux, se ha resuelto la siguiente vulnerabilidad:
net: skbuff: no dejar desplazamientos (offsets) obsoletos del encabezado después de pskb_carve()
pskb_carve_inside_header() y pskb_carve_inside_nonlinear() eliminan los primeros bytes de un paquete y vuelven a asignar skb->head.
Todos los encabezados que estaban presentes antes de la operación desaparecen, pero ambas funciones llaman a skb_headers_offset_update(skb, 0), lo cual es una operación nula (no-op): skb->mac_header, skb->network_header, skb->transport_header y skb->csum_start mantienen sus valores antiguos y ahora describen bytes que ya no existen.
Ambas auxiliares dimensionan el nuevo head a partir de la antigua skb_end_offset(), por lo que los desplazamientos obsoletos siguen quedando dentro de la nueva asignación. Sin embargo, apuntan más allá de skb_tail_pointer(), hacia bytes que nunca se inicializaron.
pskb_carve_inside_nonlinear() es el peor caso, porque deja un zombie skb con una parte lineal vacía (skb->data == skb_tail_pointer(skb), skb_headlen(skb) == 0), mientras que skb_mac_header_was_set() sigue siendo verdadero y skb->mac_header está muy por delante de skb->data.
El único usuario de pskb_extract() es rds_tcp_data_recv(), y el skb tallado se encola en tinc->ti_skb_list. Cuando se libera el mensaje entrante RDS, rds_tcp_inc_free() llama a skb_queue_purge(), que libera los skbs con SKB_DROP_REASON_QUEUE_PURGE. Esto es visible desde drop_monitor, que luego intenta extraer hacia atrás hasta el encabezado mac (falso):
skbuff: __skb_pull(len=234) skb len=6968 data_len=6968 headroom=0 headlen=0 tailroom=0 end-tail=384 mac=(234,14) mac_len=14 net=(248,40) trans=288 shinfo(txflags=0 nr_frags=1 gso(size=1428 type=16 segs=5)) csum(0x100120 start=288 offset=16 ip_summed=3 complete_sw=0 valid=1 level=0) hash(0x7b446c6c sw=0 l4=1) proto=0x86dd pkttype=0 iif=60 kernel BUG at ./include/linux/skbuff.h:2847!
Añade skb_carve_reset_headers() para marcar los encabezados mac y transport como no establecidos, restablece el network header, limpia skb->mac_len y elimina un CHECKSUM_PARTIAL ahora sin sentido (csum_start ya no describe nada).
Invalida también los desplazamientos internos. A diferencia de mac_header y transport_header, estos no tienen un valor centinela "no establecido", por lo que un valor residual distinto de cero sigue pareciendo un encabezado real. Pone a cero skb->inner_mac_header, skb->inner_network_header, skb->inner_transport_header, skb->inner_protocol y skb->encapsulation, para invalidar todo el estado del encabezado en un solo lugar.
v2: se corrigió un registro de cambios inexacto. Los desplazamientos obsoletos permanecen dentro del nuevo skb->head, que nunca es más pequeño que el anterior; simplemente apuntan más allá de skb_tail_pointer() hacia bytes que ya no existen. Gracias a Xuanqiang Luo por insistir en este punto. También se invalida el estado del encabezado interno, como sugirió la revisión AI de netdev: https://netdev-ai.bots.linux.dev/sashiko/#/patchset/20260911114922.621937-1-edumazet%40google.com
If you want to get best quality of vulnerability data, you may have to visit VulDB.