netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: "Maciej Żenczykowski" <zenczykowski@gmail.com>
To: David Miller <davem@davemloft.net>
Cc: stranche@codeaurora.org, Eric Dumazet <eric.dumazet@gmail.com>,
	Linux NetDev <netdev@vger.kernel.org>,
	samanthakumar@google.com, Eric Dumazet <edumazet@google.com>
Subject: Re: [PATCH net v2] net: udp: fix handling of CHECKSUM_COMPLETE packets
Date: Fri, 26 Oct 2018 18:53:28 -0700	[thread overview]
Message-ID: <CAHo-Oow-W13R5YYZux5zBHiuvvg8zUWb0eR5=YdcBNnpS7ee3w@mail.gmail.com> (raw)
In-Reply-To: <20181024.142105.1871980098995024381.davem@davemloft.net>

Possibly worth mentioning that without this fix you can also end up
with valid udp packets being dropped (ie. the reverse of the commit
description which talks about receiving invalid ones).

The (approximate?) requirement is:
(a) nic generates CHECKSUM_COMPLETE, but gets the actual checksum wrong
(b) udp packet is longer then 76 bytes L2 (CHECKSUM_BREAK), so we
don't calculate checksum inline prior to pulling udp header
(c) udp socket has no bpf filter, so we delay checksum until we do
copy to userspace from recvmsg()

76 bytes is 76 - 14 ether - 20 ipv4 - 8 udp header = 34 udp ipv4 payload bytes
On Wed, Oct 24, 2018 at 2:22 PM David Miller <davem@davemloft.net> wrote:
>
> From: Sean Tranchetti <stranche@codeaurora.org>
> Date: Tue, 23 Oct 2018 16:04:31 -0600
>
> > Current handling of CHECKSUM_COMPLETE packets by the UDP stack is
> > incorrect for any packet that has an incorrect checksum value.
> >
> > udp4/6_csum_init() will both make a call to
> > __skb_checksum_validate_complete() to initialize/validate the csum
> > field when receiving a CHECKSUM_COMPLETE packet. When this packet
> > fails validation, skb->csum will be overwritten with the pseudoheader
> > checksum so the packet can be fully validated by software, but the
> > skb->ip_summed value will be left as CHECKSUM_COMPLETE so that way
> > the stack can later warn the user about their hardware spewing bad
> > checksums. Unfortunately, leaving the SKB in this state can cause
> > problems later on in the checksum calculation.
> >
> > Since the the packet is still marked as CHECKSUM_COMPLETE,
> > udp_csum_pull_header() will SUBTRACT the checksum of the UDP header
> > from skb->csum instead of adding it, leaving us with a garbage value
> > in that field. Once we try to copy the packet to userspace in the
> > udp4/6_recvmsg(), we'll make a call to skb_copy_and_csum_datagram_msg()
> > to checksum the packet data and add it in the garbage skb->csum value
> > to perform our final validation check.
> >
> > Since the value we're validating is not the proper checksum, it's possible
> > that the folded value could come out to 0, causing us not to drop the
> > packet. Instead, we believe that the packet was checksummed incorrectly
> > by hardware since skb->ip_summed is still CHECKSUM_COMPLETE, and we attempt
> > to warn the user with netdev_rx_csum_fault(skb->dev);
> >
> > Unfortunately, since this is the UDP path, skb->dev has been overwritten
> > by skb->dev_scratch and is no longer a valid pointer, so we end up
> > reading invalid memory.
>
> Just want to say that it has always been complicated in this area due to
> the fact that we do this deferral of final checksum validation to when we
> copy the packet into userspace.  For example, poll() needs to do special
> things, etc.
>
> Because we have to make it seem as if we dropped the packet with a bad
> checksum from the point of view of what the user sees during recvmsg()
> and poll() calls.  But until we do that checksum validation, we don't
> know exactly what the situation is.
>
> > This patch addresses this problem in two ways:
> >       1) Do not use the dev pointer when calling netdev_rx_csum_fault()
> >          from skb_copy_and_csum_datagram_msg(). Since this gets called
> >          from the UDP path where skb->dev has been overwritten, we have
> >          no way of knowing if the pointer is still valid. Also for the
> >          sake of consistency with the other uses of
> >          netdev_rx_csum_fault(), don't attempt to call it if the
> >          packet was checksummed by software.
> >
> >       2) Add better CHECKSUM_COMPLETE handling to udp4/6_csum_init().
> >          If we receive a packet that's CHECKSUM_COMPLETE that fails
> >          verification (i.e. skb->csum_valid == 0), check who performed
> >          the calculation. It's possible that the checksum was done in
> >          software by the network stack earlier (such as Netfilter's
> >          CONNTRACK module), and if that says the checksum is bad,
> >          we can drop the packet immediately instead of waiting until
> >          we try and copy it to userspace. Otherwise, we need to
> >          mark the SKB as CHECKSUM_NONE, since the skb->csum field
> >          no longer contains the full packet checksum after the
> >          call to __skb_checksum_validate_complete().
> >
> > Fixes: e6afc8ace6dd ("udp: remove headers from UDP packets before queueing")
>
> Can't count on my hands how many regressions are a result of that change and
> it's subtle side effects. :-/
>
> > Fixes: c84d949057ca ("udp: copy skb->truesize in the first cache line")
> > Cc: Sam Kumar <samanthakumar@google.com>
> > Cc: Eric Dumazet <edumazet@google.com>
> > Signed-off-by: Sean Tranchetti <stranche@codeaurora.org>
>
> Applied and queued up for -stable, thank you.

  reply	other threads:[~2018-10-27 10:33 UTC|newest]

Thread overview: 4+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-10-23 22:04 [PATCH net v2] net: udp: fix handling of CHECKSUM_COMPLETE packets Sean Tranchetti
2018-10-24 21:21 ` David Miller
2018-10-27  1:53   ` Maciej Żenczykowski [this message]
2019-10-09 15:47 ` Maxim Mikityanskiy

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='CAHo-Oow-W13R5YYZux5zBHiuvvg8zUWb0eR5=YdcBNnpS7ee3w@mail.gmail.com' \
    --to=zenczykowski@gmail.com \
    --cc=davem@davemloft.net \
    --cc=edumazet@google.com \
    --cc=eric.dumazet@gmail.com \
    --cc=netdev@vger.kernel.org \
    --cc=samanthakumar@google.com \
    --cc=stranche@codeaurora.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).