Netdev Archive on lore.kernel.org
help / color / mirror / Atom feed
From: Willem de Bruijn <willemdebruijn.kernel@gmail.com>
To: Alexander Duyck <alexander.duyck@gmail.com>
Cc: Netdev <netdev@vger.kernel.org>,
	David Miller <davem@davemloft.net>,
	Jakub Kicinski <kuba@kernel.org>,
	Ido Schimmel <idosch@idosch.org>,
	chouhan.shreyansh630@gmail.com
Subject: Re: [PATCH net] ip_gre: validate csum_start only if CHECKSUM_PARTIAL
Date: Sat, 4 Sep 2021 17:40:07 -0400	[thread overview]
Message-ID: <CA+FuTScCp7EB4bLfrTADia5pOfDwsLNxN0pkWjLN_+CefYNTkg@mail.gmail.com> (raw)
In-Reply-To: <CAKgT0Ud5ZFQ3Jv4DAFftf6OkhJe5UxEcuVTJs-9HYk8ptCt9Uw@mail.gmail.com>

On Sat, Sep 4, 2021 at 11:37 AM Alexander Duyck
<alexander.duyck@gmail.com> wrote:
>
> On Sat, Sep 4, 2021 at 7:46 AM Willem de Bruijn
> <willemdebruijn.kernel@gmail.com> wrote:
> >
> > On Fri, Sep 3, 2021 at 7:27 PM Alexander Duyck
> > <alexander.duyck@gmail.com> wrote:
> > >
> > > On Fri, Sep 3, 2021 at 12:38 PM Willem de Bruijn
> > > <willemdebruijn.kernel@gmail.com> wrote:
> > > >
> > >
> > > <snip>
> > >
> > > > > whereas if the offset is stored somewhere in the unstripped data we
> > > > > could then drop the packet and count it as a drop without having to
> > > > > modify the frame via the skb_pull.
> > > >
> > > > This is a broader issue that userspace can pass any csum_start as long
> > > > as it is within packet bounds. We could address it here specifically
> > > > for the GRE header. But that still leaves many potentially bad offsets
> > > > further in the packet in this case, and all the other cases. Checking
> > > > that specific header seems a bit arbitrary to me, and might actually
> > > > give false confidence.
> > > >
> > > > We could certainly move the validation from gre_handle_offloads to
> > > > before skb_pull, to make it more obvious *why* the check exists.
> > >
> > > Agreed. My main concern is that the csum_start is able to be located
> > > somewhere where the userspace didn't write. For the most part the
> > > csum_start and csum_offset just needs to be restricted to the regions
> > > that the userspace actually wrote to.
> >
> > I don't quite follow. Even with this bug, the offset is somewhere userspace
> > wrote. That data is just pulled.
>
> Sorry, I was thinking of the SOCK_DGRAM case where the header is added
> via a call to dev_hard_header().
>
> > > > > Maybe for those
> > > > > cases we need to look at adding an unsigned int argument to
> > > > > virtio_net_hdr_to_skb in which we could pass 0 for the unused case or
> > > > > dev->hard_header_len in the cases where we have something like
> > > > > af_packet that is transmitting over an ipgre tunnel. The general idea
> > > > > is to prevent these virtio_net_hdr_to_skb calls from pointing the
> > > > > csum_start into headers that userspace was not responsible for
> > > > > populating.
> > > >
> > > > One issue with that is that dev->hard_header_len itself is imprecise
> > > > for protocols with variable length link layer headers. There, too, we
> > > > have had a variety of bug fixes in the past.
> > > >
> > > > It also adds cost to every user of virtio_net_hdr, while we only know
> > > > one issue in a rare case of the IP_GRE device.
> > >
> > > Quick question, the assumption is that the checksum should always be
> > > performed starting no earlier than the transport header right? Looking
> > > over virtio_net_hdr_to_skb it looks like it is already verifying the
> > > transport header is in the linear portion of the skb. I'm wondering if
> > > we couldn't just look at adding a check to verify the transport offset
> > > is <= csum start? We might also be able to get rid of one of the two
> > > calls to pskb_may_pull by doing that.
> >
> > Are you referring to this part in the .._NEEDS_CSUM branch?
> >
> >                 if (!skb_partial_csum_set(skb, start, off))
> >                         return -EINVAL;
> >
> >                 p_off = skb_transport_offset(skb) + thlen;
> >                 if (!pskb_may_pull(skb, p_off))
> >                         return -EINVAL;
> >
> > skb_partial_csum_set is actually what sets the transport offset,
> > derived from start.
>
> Ugh, I had overlooked that as I was more focused on the
> skb_probe_transport_header calls in the af_packet code.
>
> So we can have both the transport offset and the csum_start in a
> region that gets stripped by the ipgre code. Worse yet the inner
> transport header will also be pointing somewhere outside of the
> encapsulated region when we pass it off to skb_reset_inner_headers().
>
> Maybe it would make sense to just have the check look into the
> transport offset instead of csum start as that way you are essentially
> addressing two possible issues instead of one, and it would
> effectively combine multiple checks as the uninitialized value is ~0
> which should always be greater than "skb_headroom + tunnel->hlen +
> sizeof(struct iphdr)". I think you mentioned before placing a check
> just before you make the call to skb_pull in the GRE transmit path.
> Doing that we would at least reduce the impact as it would only apply
> in the header_ops case in ipgre_xmit instead of being applied to all
> the transmit paths which don't perform the pull.

Do you mean

        if (dev->header_ops) {
+               int pull_len = tunnel->hlen + sizeof(struct iphdr);
+
                if (skb_cow_head(skb, 0))
                        goto free_skb;

                tnl_params = (const struct iphdr *)skb->data;

+               if (pull_len > skb_transport_offset(skb))
+                       goto free_skb;
+
                /* Pull skb since ip_tunnel_xmit() needs skb->data pointing
                 * to gre header.
                 */
-               skb_pull(skb, tunnel->hlen + sizeof(struct iphdr));
+               skb_pull(skb, pull_len);
                skb_reset_mac_header(skb);

plus then

 static int gre_handle_offloads(struct sk_buff *skb, bool csum)
 {
-       /* Local checksum offload requires csum offload of the inner packet */
-       if (csum && skb->ip_summed == CHECKSUM_PARTIAL &&
-           skb_checksum_start(skb) < skb->data)
-               return -EINVAL;
-
        return iptunnel_handle_offloads(skb, csum ? SKB_GSO_GRE_CSUM :
SKB_GSO_GRE);
 }

  reply	other threads:[~2021-09-04 21:40 UTC|newest]

Thread overview: 21+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-09-02 19:34 [PATCH net] ip6_gre: " Willem de Bruijn
2021-09-02 19:34 ` [PATCH net] ip_gre: " Willem de Bruijn
2021-09-02 20:25   ` Alexander Duyck
2021-09-02 20:29     ` Willem de Bruijn
2021-09-02 21:17       ` Alexander Duyck
2021-09-02 21:44         ` Willem de Bruijn
2021-09-03  2:01           ` Alexander Duyck
2021-09-03  2:40             ` Willem de Bruijn
2021-09-03 16:46               ` Alexander Duyck
2021-09-03 19:38                 ` Willem de Bruijn
2021-09-03 23:13                   ` Alexander Duyck
2021-09-04 14:45                     ` Willem de Bruijn
2021-09-04 15:35                       ` Alexander Duyck
2021-09-04 21:40                         ` Willem de Bruijn [this message]
2021-09-04 21:53                           ` Alexander Duyck
2021-09-04 22:05                             ` Willem de Bruijn
2021-09-04 23:47                               ` Alexander Duyck
2021-09-05 15:24                                 ` Willem de Bruijn
2021-09-05 15:53                                   ` Alexander Duyck
2021-09-06  3:02                                     ` Willem de Bruijn
2021-09-02 20:27 ` [PATCH net] ip6_gre: " Alexander Duyck

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+FuTScCp7EB4bLfrTADia5pOfDwsLNxN0pkWjLN_+CefYNTkg@mail.gmail.com \
    --to=willemdebruijn.kernel@gmail.com \
    --cc=alexander.duyck@gmail.com \
    --cc=chouhan.shreyansh630@gmail.com \
    --cc=davem@davemloft.net \
    --cc=idosch@idosch.org \
    --cc=kuba@kernel.org \
    --cc=netdev@vger.kernel.org \
    --subject='Re: [PATCH net] ip_gre: validate csum_start only if CHECKSUM_PARTIAL' \
    /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

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).