[Saucy] [PATCH] SRU: zerocopy LSO segmenting fixed

Luis Henriques luis.henriques at canonical.com
Mon Jun 23 13:53:27 UTC 2014


On Sun, Jun 22, 2014 at 11:07:42AM +0300, Anton Nayshtut wrote:
> BugLink: https://bugs.launchpad.net/bugs/1328973
> 
> [SRU Justification]
> 
> [Setup]
>  - 2 or more QEMU Guest VMs sharing the the same host
>  - the Guests are communicating using virtio-net-pci devices
>  - vhost-net is enabled
> 
> [Explanation]
> If one Guest VM sends GSO packets to another while GRO is disabled for receiver,
> so these packets are segmented by net/core.
> In this case, if zero-copy is enabled in vhost-net, the GSO packets TX
> completion is reported to userspace as before the TX is actually done.
> The vhost-net's zero-copy mechanism is enabled by default since v3.8-rc1
> (f9611c43).
> 
> [Impact]
> Incorrect/junk data sent in case the transmitting Guest OS re-uses/frees the TX
> buffer immediately upon TX completion.
> 
> [Test Case]
> Windows 2008R2 Guest VMs running MS HCK Offload LSO test.
> NOTE1: GRO is always disabled in this case because it's not supported by Windows
> Guest virtio-net-pci drivers.
> NOTE2: MS HCK re-uses the GSO (LSO) buffers, so it reproduces the issue every
> time.
> 
>    skbuff: skb_segment: orphan frags before copying
> 
>     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.
> 
>     OriginalAuthor: Michael S. Tsirkin <mst at redhat.com>
>     Signed-off-by: Michael S. Tsirkin <mst at redhat.com>
>     Acked-by: Herbert Xu <herbert at gondor.apana.org.au>
>     Signed-off-by: David S. Miller <davem at davemloft.net>
> 
>     (cherry picked from commit 1fd819ecb90cc9b822cd84d3056ddba315d3340f)
>     CVE-2014-0131
>     Signed-off-by: Andy Whitcroft <apw at canonical.com>
>     (backported from 0f860fb4f583909ed999df58abf57ff40ec94d6d ubuntu-trusty)
>     Signed-off-by: Anton Nayshtut <anton at swortex.com>
> 

This patch is included in the 3.11 extended stable currently under
review[1].  Since Saucy picks the 3.11 extended stable releases, this
patch would be included in the Saucy kernel anyway (Note:
lts-backport-saucy kernels are about to reach EOL!).

However, the backport is I have for the 3.11 kernel is different[2]
from this one and I am not able to decide which is correct one.

For the 3.11 kernel I have picked the version provided by Ben Hutching
to the stable mailing list[3].  This version is currently being used
in the Lucid kernel, and has been released on the 3.8 extended
stable.

[1] https://lkml.org/lkml/2014/6/23/368
[2] https://lkml.org/lkml/2014/6/23/400
[3] http://thread.gmane.org/gmane.linux.kernel.stable/93422

Cheers,
--
Luís

> ---
>  net/core/skbuff.c |    4 ++++
>  1 file changed, 4 insertions(+)
> 
> diff --git a/net/core/skbuff.c b/net/core/skbuff.c
> index abcad83..586bca9 100644
> --- a/net/core/skbuff.c
> +++ b/net/core/skbuff.c
> @@ -2729,6 +2729,7 @@ struct sk_buff *skb_segment(struct sk_buff *skb, netdev_features_t features)
>  	struct sk_buff *fskb = skb_shinfo(skb)->frag_list;
>  	unsigned int mss = skb_shinfo(skb)->gso_size;
>  	unsigned int doffset = skb->data - skb_mac_header(skb);
> +	struct sk_buff *frag_skb = skb;
>  	unsigned int offset = doffset;
>  	unsigned int tnl_hlen = skb_tnl_header_len(skb);
>  	unsigned int headroom;
> @@ -2769,6 +2770,7 @@ struct sk_buff *skb_segment(struct sk_buff *skb, netdev_features_t features)
>  		if (!hsize && i >= nfrags) {
>  			BUG_ON(fskb->len != len);
>  
> +			frag_skb = fskb;
>  			pos += len;
>  			nskb = skb_clone(fskb, GFP_ATOMIC);
>  			fskb = fskb->next;
> @@ -2838,6 +2840,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(frag_skb, GFP_ATOMIC)))
> +				goto err;
>  			*frag = skb_shinfo(skb)->frags[i];
>  			__skb_frag_ref(frag);
>  			size = skb_frag_size(frag);
> -- 
> 1.7.9.5
> 
> 
> -- 
> kernel-team mailing list
> kernel-team at lists.ubuntu.com
> https://lists.ubuntu.com/mailman/listinfo/kernel-team




More information about the kernel-team mailing list