skbuff: skb_segment: orphan frags before copying
authorMichael S. Tsirkin <mst@redhat.com>
Mon, 10 Mar 2014 17:28:08 +0000 (19:28 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 1 Jul 2014 03:09:45 +0000 (20:09 -0700)
commit 1fd819ecb90cc9b822cd84d3056ddba315d3340f upstream.

skb_segment copies frags around, so we need
to copy them carefully to avoid accessing
user memory after reporting completion to userspace
through a callback.

skb_segment doesn't normally happen on datapath:
TSO needs to be disabled - so disabling zero copy
in this case does not look like a big deal.

Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Acked-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: David S. Miller <davem@davemloft.net>
[bwh: Backported to 3.2.  As skb_segment() only supports page-frags *or* a
  frag list, there is no need for the additional frag_skb pointer or the
  preparatory renaming.]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
Cc: Eddie Chapman <eddie@ehuk.net> # backported to 3.10
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
net/core/skbuff.c

index 66f722b5052a3a6647872730d6b34bc4be5f9dab..9f84a5f7404d4b2ae38f78a94152ef72010c50ef 100644 (file)
@@ -2844,6 +2844,8 @@ struct sk_buff *skb_segment(struct sk_buff *skb, netdev_features_t features)
                skb_shinfo(nskb)->tx_flags = skb_shinfo(skb)->tx_flags & SKBTX_SHARED_FRAG;
 
                while (pos < offset + len && i < nfrags) {
+                       if (unlikely(skb_orphan_frags(skb, GFP_ATOMIC)))
+                               goto err;
                        *frag = skb_shinfo(skb)->frags[i];
                        __skb_frag_ref(frag);
                        size = skb_frag_size(frag);