HIGH Introduced in 4.7
skbuff HeaderOffset OOB
CVE-2026-98271
CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:H
01Description
In the Linux kernel, the following vulnerability has been resolved: net: skbuff: do not leave stale header offsets after pskb_carve() pskb_carve_inside_header() and pskb_carve_inside_nonlinear() remove the first bytes of a packet and reallocate skb->head. All the headers that were present before the operation are gone, but both functions call skb_headers_offset_update(skb, 0), which is a no-op : skb->mac_header, skb->network_header, skb->transport_header and skb->csum_start keep their old values and now describe bytes which are no longer there. Both helpers size the new head from the old skb_end_offset(), so the stale offsets still land inside the new allocation. They point past skb_tail_pointer() though, to bytes that were never initialized. pskb_carve_inside_nonlinear() is the worst case, because it leaves a zombie skb with an empty linear part (skb->data == skb_tail_pointer(skb), skb_headlen(skb) == 0), while skb_mac_header_was_set() is still true and skb->mac_header is way ahead of skb->data. The only user of pskb_extract() is rds_tcp_data_recv(), and the carved skb is queued on tinc->ti_skb_list. When the RDS incoming message is released, rds_tcp_inc_free() calls skb_queue_purge(), which frees the skbs with SKB_DROP_REASON_QUEUE_PURGE. This is visible from drop_monitor, which then tries to pull back to the (bogus) mac header : 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! Add skb_carve_reset_headers() to mark the mac and transport headers as not set, reset the network header, clear skb->mac_len, and drop a now meaningless CHECKSUM_PARTIAL (csum_start no longer describes anything). Invalidate the inner offsets as well. Unlike mac_header and transport_header they have no "unset" sentinel, so a leftover non-zero value still looks like a real header. Zero skb->inner_mac_header, skb->inner_network_header, skb->inner_transport_header, skb->inner_protocol and skb->encapsulation, so that all the header state is invalidated in one place. v2: fixed an inaccurate changelog. The stale offsets stay inside the new skb->head, which is never smaller than the old one, they simply point past skb_tail_pointer() to bytes that are gone. Thanks to Xuanqiang Luo for insisting on this. Also invalidate the inner header state, as suggested by the netdev AI review : https://netdev-ai.bots.linux.dev/sashiko/#/patchset/20260911114922.621937-1-edumazet%40google.com
02KernelScan AI Analysis
Risk summary
A network attacker sending RDS-TCP traffic to a system with the RDS-TCP kernel module loaded and configured can trigger a kernel crash. The bug leaves stale header offsets in packet buffers after a carve operation, causing the kernel to read uninitialized memory and hit a BUG_ON when any consumer accesses those headers. Systems not running RDS-TCP are unaffected.
Vulnerability analysis
When the kernel removes bytes from the front of a network packet buffer and reallocates the buffer header, it fails to reset the stored offsets for the MAC, network, transport, and checksum headers. These offsets keep their old values and now point past the valid data area into uninitialized memory within the allocation. When any consumer of the buffer later tries to access these headers — for example, the drop monitoring subsystem pulling back to the MAC header — it reads garbage and triggers a kernel crash. The fix adds a helper that properly invalidates all header offsets, inner header state, and checksum state after the carving operation, so no consumer can mistake the stale values for real headers. The only code path that reaches this bug is the RDS-over-TCP transport receiving data over a TCP connection, which requires the RDS-TCP kernel module to be loaded and configured; an attacker sending TCP traffic to such a system can trigger the crash without authentication.
Lifecycle
03Fix Versions
| Branch | Introduced | Fixed in | Patch commit |
|---|---|---|---|
| 6.12 | 4.7 | 6.12.112 | 75e4a3e62531 |
| 6.18 | 4.7 | 6.18.54 | bff8a8e53a6d |
| 7.2 | 4.7 | 7.2.8 | 12929ed66a51 |
| mainline | 4.7 | 7.3-rc4 | a5117e1eccac |