From: sashiko-bot@kernel.org
To: "Michael S. Tsirkin" <mst@redhat.com>
Cc: virtualization@lists.linux.dev, "Eugenio Perez" <eperezma@redhat.com>
Subject: Re: [PATCH net v5 7/7] virtio_net: cleanup protocol calculation
Date: Fri, 23 Oct 2026 12:59:08 +0000 [thread overview]
Message-ID: <sashiko-outbox-182808@kernel.org> (raw)
In-Reply-To: <f8621d16cf0c67335641d07c1555ec1e43f17628.1792668082.git.mst@redhat.com>
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [High] net: use-after-free read of iph->ihl after pskb_may_pull() in ip4_parse()
- [High] virtio_net: failed drop of invalid non-GSO tunnel packets in virtio_net_hdr_tnl_to_skb()
--
commit 932b3459605ba3055ae9042b1894bc6eb02c03c4
Author: Michael S. Tsirkin <mst@redhat.com>
virtio_net: cleanup protocol calculation
This commit removes a duplicate assignment of inner_proto in
virtio_net_hdr_tnl_to_skb() by computing it once before calling
skb_set_inner_protocol().
> diff --git a/include/linux/virtio_net.h b/include/linux/virtio_net.h
> index 063cc116e51a1..e984e446ba44a 100644
> --- a/include/linux/virtio_net.h
> +++ b/include/linux/virtio_net.h
> @@ -613,8 +613,8 @@ virtio_net_hdr_tnl_to_skb(struct sk_buff *skb,
> return -EINVAL;
> }
>
> - skb_set_inner_protocol(skb, inner_isv6 ? htons(ETH_P_IPV6) :
> - htons(ETH_P_IP));
> + inner_proto = inner_isv6 ? htons(ETH_P_IPV6) : htons(ETH_P_IP);
> + skb_set_inner_protocol(skb, inner_proto);
> if (hdr->flags & VIRTIO_NET_HDR_F_UDP_TUNNEL_CSUM) {
> if (!tnl_csum_negotiated)
> return -EINVAL;
> @@ -638,7 +638,6 @@ virtio_net_hdr_tnl_to_skb(struct sk_buff *skb,
> * We know VIRTIO_NET_HDR_F_NEEDS_CSUM was set so __virtio_net_hdr_to_skb
> * set CHECKSUM_PARTIAL.
> */
> - inner_proto = inner_isv6 ? htons(ETH_P_IPV6) : htons(ETH_P_IP);
> if (virtio_net_csum_partial_ok_at_offset(skb, gso_inner_type, inner_nh,
> inner_proto))
> return 0;
[Severity: High]
When virtio_net_csum_partial_ok_at_offset() validates an IPv4 header via
virtio_net_l4_start() -> ip4_parse() (introduced earlier in this series in
commit f0109d51e8b0 ("net: add ip4_parse()")), can ip4_parse() in
include/linux/ip.h perform a use-after-free read of iph->ihl?
In include/linux/ip.h:ip4_parse():
if (!pskb_may_pull(skb, nhoff + sizeof(struct iphdr)))
return NULL;
iph = (struct iphdr *)(skb->data + nhoff);
if (iph->version != 4 || iph->ihl < sizeof(struct iphdr) / sizeof(u32))
return NULL;
/* Pull the options as well: the transport header offset
* returned below must be within the linear data.
*/
if (!pskb_may_pull(skb, nhoff + iph->ihl * sizeof(u32)))
return NULL;
*thoff = nhoff + iph->ihl * sizeof(u32);
return (struct iphdr *)(skb->data + nhoff);
When an IPv4 packet has options (iph->ihl > 5) that reside in nonlinear
paged data (so nhoff + iph->ihl * sizeof(u32) > skb_headlen(skb)), or when
the skb is cloned, the second pskb_may_pull() call invokes
__pskb_pull_tail() -> pskb_expand_head(), which allocates a new skb->head
buffer and frees the old buffer still pointed to by iph.
Dereferencing iph->ihl to compute *thoff after the second pskb_may_pull()
then reads from the freed buffer before iph is reloaded from
skb->data + nhoff. This affects all callers of ip4_parse(), including
ip_rcv_core(), virtio_net_l4_start(), br_validate_ipv4(), and
nf_reject_iphdr_validate().
Should ip4_parse() cache iph->ihl * sizeof(u32) in a local variable before
the second pskb_may_pull() call, or reload iph from skb->data + nhoff first?
[Severity: High]
Also in include/linux/virtio_net.h:virtio_net_hdr_tnl_to_skb(), what happens
when virtio_net_csum_partial_ok_at_offset() returns false for a non-gso
packet with a tunnel header?
Earlier in virtio_net_hdr_tnl_to_skb(), __virtio_net_hdr_to_skb() only sets
shinfo->gso_size and shinfo->gso_type when skb->len - nh_off > gso_size. If
a caller provides gso_size >= skb->len - nh_off, skb_is_gso(skb) remains
false, which virtio_net_hdr_tnl_to_skb() explicitly accounts for after
setting the inner header offsets and skb->encapsulation:
skb->inner_transport_header = inner_th + skb_headroom(skb);
skb->inner_network_header = inner_nh + skb_headroom(skb);
skb->inner_mac_header = inner_nh + skb_headroom(skb);
skb->transport_header = outer_th + skb_headroom(skb);
skb->encapsulation = 1;
if (!skb_is_gso(skb))
skb_shinfo(skb)->gso_type &= ~(SKB_GSO_UDP_TUNNEL_CSUM |
SKB_GSO_UDP_TUNNEL);
/*
* We know VIRTIO_NET_HDR_F_NEEDS_CSUM was set so __virtio_net_hdr_to_skb
* set CHECKSUM_PARTIAL.
*/
if (virtio_net_csum_partial_ok_at_offset(skb, gso_inner_type, inner_nh,
inner_proto))
return 0;
/* A tunnel header implies GSO, so drop. */
return __virtio_net_resolve_csum_partial_mismatch(skb);
However, in include/linux/virtio_net.h:__virtio_net_resolve_csum_partial_mismatch():
static inline int __virtio_net_resolve_csum_partial_mismatch(struct sk_buff *skb)
{
if (skb_is_gso(skb))
return -EINVAL;
return skb_checksum_help(skb) ?: 1;
}
When !skb_is_gso(skb) and virtio_net_csum_partial_ok_at_offset() fails
because the inner headers are malformed or do not match inner_th,
__virtio_net_resolve_csum_partial_mismatch(skb) does not drop the packet.
Instead, it completes the inner checksum via skb_checksum_help(skb) and
returns 1, which callers treat as success.
Does this allow a non-gso tunnel packet with invalid inner headers to enter
the networking stack with skb->encapsulation = 1, unvalidated inner header
offsets, and any requested outer tunnel checksum
(VIRTIO_NET_HDR_F_UDP_TUNNEL_CSUM) lost when skb_checksum_help() sets
ip_summed to CHECKSUM_NONE? Should virtio_net_hdr_tnl_to_skb() return
-EINVAL directly when virtio_net_csum_partial_ok_at_offset() returns false?
--
Sashiko AI review · https://sashiko.dev/#/patchset/cover.v5.git.mst@redhat.com?part=7
next prev parent reply other threads:[~2026-10-23 12:59 UTC|newest]
Thread overview: 28+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-22 12:57 [PATCH net v5 0/7] more virtio-net csum hardening Michael S. Tsirkin
2026-10-22 12:57 ` [PATCH net v5 1/7] net: account for ingress-resolved virtio net hdr state Michael S. Tsirkin
2026-10-22 14:37 ` Willem de Bruijn
2026-10-23 12:59 ` sashiko-bot
2026-10-25 5:30 ` netdev-bot+sashiko
2026-10-22 12:58 ` [PATCH net v5 2/7] um: vector: trim skbs before verifying the header Michael S. Tsirkin
2026-10-23 12:59 ` sashiko-bot
2026-10-25 5:31 ` netdev-bot+sashiko
2026-10-22 12:58 ` [PATCH net v5 3/7] virtio_net: parse tunnel csum_start little-endian Michael S. Tsirkin
2026-10-23 12:59 ` sashiko-bot
2026-10-22 12:58 ` [PATCH net v5 4/7] net: resolve uncommon partial checksums at ingress Michael S. Tsirkin
2026-10-22 14:52 ` Willem de Bruijn
2026-10-22 15:49 ` Michael S. Tsirkin
2026-10-22 17:52 ` Chris Arges
2026-10-22 23:38 ` Michael S. Tsirkin
2026-10-23 1:38 ` Chris Arges
2026-10-23 12:59 ` sashiko-bot
2026-10-25 5:31 ` netdev-bot+sashiko
2026-10-22 12:58 ` [PATCH net v5 5/7] net: add a sysctl to opt out of virtio net hdr checksum validation Michael S. Tsirkin
2026-10-23 12:59 ` sashiko-bot
2026-10-25 5:31 ` netdev-bot+sashiko
2026-10-22 12:58 ` [PATCH net v5 6/7] net: add ip4_parse() Michael S. Tsirkin
2026-10-23 12:59 ` sashiko-bot
2026-10-25 5:31 ` netdev-bot+sashiko
2026-10-22 12:58 ` [PATCH net v5 7/7] virtio_net: cleanup protocol calculation Michael S. Tsirkin
2026-10-23 12:59 ` sashiko-bot [this message]
2026-10-25 5:31 ` netdev-bot+sashiko
2026-10-22 17:54 ` [PATCH net v5 0/7] more virtio-net csum hardening Chris Arges
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=sashiko-outbox-182808@kernel.org \
--to=sashiko-bot@kernel.org \
--cc=eperezma@redhat.com \
--cc=mst@redhat.com \
--cc=sashiko-reviews@lists.linux.dev \
--cc=virtualization@lists.linux.dev \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox