CVE-2026-98954: net: always dissect GSO packets in __virtio_net_hdr_to_skb()

Published Oct 23, 2026
·
Updated

In the Linux kernel, the following vulnerability has been resolved:

net: always dissect GSO packets in virtionethdrtoskb()

Commit 9e8db5913264 ("net: avoid false positives in untrusted gso validation") added a '&& skb->networkheader' check before flow-dissecting GSO packets without VIRTIONETHDRFNEEDSCSUM in virtionethdrtoskb(), because some callers (such as tungetuser(), tunxdpone(), virtnetreceivedone(), and rawverifyheader()) called virtionethdrtoskb() before initializing skb->networkheader and skb->dev.

Because allocskb() and buildskbaround() zero-initialize skb->networkheader to 0 (unlike macheader and transportheader which are initialized to ~0U), those four callers always had skb->networkheader == 0 and bypassed flow dissection in virtionethdrtoskb(). More generally, skb->networkheader is an offset from skb->head (where 0 is also a valid offset whenever skbheadroom(skb) is 0), not a boolean flag.

Whenever the 'if (gsotype && skb->networkheader)' branch was skipped, the fallback 'else if (gsotype)' only pulled nhminlen + thlen (40 bytes for TCPv4) without dissecting the packet, without validating ipproto or nproto, and without setting skb->transportheader.

If the packet has a malformed network header, it is not rejected and a subsequent skbprobetransportheader() also fails, leaving skb->transportheader at ~0U (0xffff). Similarly, if an IPv4 packet carries IP options (ihl > 5) or an IPv6 packet carries extension headers, pulling only nhminlen + thlen can leave the TCP header outside skb->head. In both cases, tcphdrlen(skb) in skbgsotransportseglen() reads out-of-bounds:

BUG: KASAN: slab-out-of-bounds in skbgsotransportseglen Read of size 2 by task poc/133 skbgsotransportseglen (net/core/gso.c:155) skbgsovalidatemaclen (net/core/gso.c:270) tbfenqueue (net/sched/schtbf.c:260) devqdiscenqueue (net/core/dev.c:4227) devqueuexmit (net/core/dev.c:4884)

In addition, checking virtionethdrmatchproto() only inside 'if (!skb->protocol)' before flow dissection both skipped validation when skb->protocol was pre-set by the caller and rejected VLAN-tagged frames whose outer L2 protocol is ETHP8021Q or ETHP8021AD.

Fix this by: 1. Initializing skb->dev and skb->networkheader (plus skb->protocol for IFFTUN) before virtionethdrtoskb() in tungetuser(), tunxdpone(), virtnetreceivedone(), and rawverifyheader(). In tungetuser(), drop the redundant skbresetmacheader(skb) in the IFFTUN case since virtionethdrtoskb() unconditionally resets macheader. 2. Removing '&& skb->networkheader' and the unvalidated 'else if (gsotype)' fallback in virtionethdrtoskb() so all GSO packets without VIRTIONETHDRFNEEDSCSUM are flow-dissected, have their transport header pulled into linear data, and have skb->transportheader set. 3. Moving the virtionethdrmatchproto() check to after skbflowdissectflowkeysbasic(), validating keys.basic.nproto against hdrgsotype.

Affected Software

1 affected component
Linux Linux kernel

Remediation

Recommended actions to resolve this vulnerability, in priority order.

  1. Compensating control

    Modify the Linux kernel networking code so __virtio_net_hdr_to_skb() always dissects GSO packets: remove the && skb->network_header guard, move virtio_net_hdr_match_proto() validation until after skb_flow_dissect_flow_keys_basic(), validate keys.basic.n_proto against hdr_gso_type, and initialize skb->dev, skb->network_header, and skb->transport_header before processing. In tun_get_user(), set the IFF_TUN context before calling virtio_net_hdr_*_to_skb() and drop the redundant skb_reset_mac_header(skb).

Event History

Oct 23, 2026
CVE Published
via MITRE·12:19 PM
Data Sourced
via MITRE·12:19 PM
Description

Contact

SecAlerts Pty Ltd.
132 Wickham Terrace
Fortitude Valley,
QLD 4006, Australia
info@secalerts.co
By using SecAlerts services, you agree to our services end-user license agreement. This website is safeguarded by reCAPTCHA and governed by the Google Privacy Policy and Terms of Service. All names, logos, and brands of products are owned by their respective owners, and any usage of these names, logos, and brands for identification purposes only does not imply endorsement. If you possess any content that requires removal, please get in touch with us.
© 2026 SecAlerts Pty Ltd.
ABN: 70 645 966 203, ACN: 645 966 203