netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Willem de Bruijn <willemdebruijn.kernel@gmail.com>
To: Jason Wang <jasowang@redhat.com>
Cc: Balazs Nemeth <bnemeth@redhat.com>,
	Network Development <netdev@vger.kernel.org>,
	linux-kernel <linux-kernel@vger.kernel.org>,
	"Michael S. Tsirkin" <mst@redhat.com>,
	David Miller <davem@davemloft.net>,
	virtualization@lists.linux-foundation.org
Subject: Re: [PATCH] net: check if protocol extracted by virtio_net_hdr_set_proto is correct
Date: Fri, 19 Feb 2021 09:55:28 -0500	[thread overview]
Message-ID: <CA+FuTSf2GCi+RzpkFeBgtSOyhjsBFfApjekzupHLfyeYDn-JYQ@mail.gmail.com> (raw)
In-Reply-To: <2cc06597-8005-7be8-4094-b20f525afde8@redhat.com>

On Fri, Feb 19, 2021 at 3:53 AM Jason Wang <jasowang@redhat.com> wrote:
>
>
> On 2021/2/18 11:50 下午, Willem de Bruijn wrote:
> > On Thu, Feb 18, 2021 at 10:01 AM Balazs Nemeth <bnemeth@redhat.com> wrote:
> >> For gso packets, virtio_net_hdr_set_proto sets the protocol (if it isn't
> >> set) based on the type in the virtio net hdr, but the skb could contain
> >> anything since it could come from packet_snd through a raw socket. If
> >> there is a mismatch between what virtio_net_hdr_set_proto sets and
> >> the actual protocol, then the skb could be handled incorrectly later
> >> on by gso.
> >>
> >> The network header of gso packets starts at 14 bytes, but a specially
> >> crafted packet could fool the call to skb_flow_dissect_flow_keys_basic
> >> as the network header offset in the skb could be incorrect.
> >> Consequently, EINVAL is not returned.
> >>
> >> There are even packets that can cause an infinite loop. For example, a
> >> packet with ethernet type ETH_P_MPLS_UC (which is unnoticed by
> >> virtio_net_hdr_to_skb) that is sent to a geneve interface will be
> >> handled by geneve_build_skb. In turn, it calls
> >> udp_tunnel_handle_offloads which then calls skb_reset_inner_headers.
> >> After that, the packet gets passed to mpls_gso_segment. That function
> >> calculates the mpls header length by taking the difference between
> >> network_header and inner_network_header. Since the two are equal
> >> (due to the earlier call to skb_reset_inner_headers), it will calculate
> >> a header of length 0, and it will not pull any headers. Then, it will
> >> call skb_mac_gso_segment which will again call mpls_gso_segment, etc...
> >> This leads to the infinite loop.
>
>
> I remember kernel will validate dodgy gso packets in gso ops. I wonder
> why not do the check there? The reason is that virtio/TUN is not the
> only source for those packets.

It is? All other GSO packets are generated by the stack itself, either
locally or through GRO.

But indeed some checks are better performed in the GSO layer. Such as
likely the 0-byte mpls header length.

If we cannot trust virtio_net_hdr.gso_type passed from userspace, then
we can also not trust the eth.h_proto coming from the same source. But
it makes sense to require them to be consistent. There is a
dev_parse_header_protocol that may return the link layer type in a
more generic fashion than casting to skb_eth_hdr.

Question remains what to do for the link layer types that do not implement
header_ops->parse_protocol, and so we cannot validate the packet's
network protocol. Drop will cause false positives, accepts will leave a
potential path, just closes it for Ethernet.

This might call for multiple fixes, both on first ingest and inside the stack?

  reply	other threads:[~2021-02-19 14:57 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-02-18 14:57 [PATCH] net: check if protocol extracted by virtio_net_hdr_set_proto is correct Balazs Nemeth
2021-02-18 15:50 ` Willem de Bruijn
2021-02-19  8:51   ` Jason Wang
2021-02-19 14:55     ` Willem de Bruijn [this message]
2021-02-22  3:39       ` Jason Wang
2021-02-23 13:42         ` Balazs Nemeth
2021-02-23 14:22           ` Willem de Bruijn

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=CA+FuTSf2GCi+RzpkFeBgtSOyhjsBFfApjekzupHLfyeYDn-JYQ@mail.gmail.com \
    --to=willemdebruijn.kernel@gmail.com \
    --cc=bnemeth@redhat.com \
    --cc=davem@davemloft.net \
    --cc=jasowang@redhat.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mst@redhat.com \
    --cc=netdev@vger.kernel.org \
    --cc=virtualization@lists.linux-foundation.org \
    /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;
as well as URLs for NNTP newsgroup(s).