[kernel] r21998 - in dists/sid/linux/debian: . patches patches/bugfix/all

Ben Hutchings benh at moszumanska.debian.org
Fri Oct 31 02:28:46 UTC 2014


Author: benh
Date: Fri Oct 31 02:28:46 2014
New Revision: 21998

Log:
drivers/net,ipv6: Fix virtio/IPv6 regression in 3.16

Added:
   dists/sid/linux/debian/patches/bugfix/all/drivers-net-Disable-UFO-through-virtio.patch
   dists/sid/linux/debian/patches/bugfix/all/drivers-net-ipv6-Select-IPv6-fragment-idents-for-vir.patch
Modified:
   dists/sid/linux/debian/changelog
   dists/sid/linux/debian/patches/series

Modified: dists/sid/linux/debian/changelog
==============================================================================
--- dists/sid/linux/debian/changelog	Fri Oct 31 02:23:45 2014	(r21997)
+++ dists/sid/linux/debian/changelog	Fri Oct 31 02:28:46 2014	(r21998)
@@ -129,6 +129,9 @@
     (Closes: #767148)
   * wireless: rt2x00: add new rt2800usb device (thanks to Cyril Brulebois)
     (Closes: #766802)
+  * drivers/net,ipv6: Fix virtio/IPv6 regression in 3.16:
+    - drivers/net: Disable UFO through virtio
+    - drivers/net,ipv6: Select IPv6 fragment idents for virtio UFO packets
 
   [ Mauricio Faria de Oliveira ]
   * [ppc64el] Disable CONFIG_CMDLINE{,_BOOL} usage for setting consoles

Added: dists/sid/linux/debian/patches/bugfix/all/drivers-net-Disable-UFO-through-virtio.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/sid/linux/debian/patches/bugfix/all/drivers-net-Disable-UFO-through-virtio.patch	Fri Oct 31 02:28:46 2014	(r21998)
@@ -0,0 +1,212 @@
+From: Ben Hutchings <ben at decadent.org.uk>
+Date: Thu, 30 Oct 2014 18:27:12 +0000
+Subject: [1/2] drivers/net: Disable UFO through virtio
+Origin: https://git.kernel.org/cgit/linux/kernel/git/davem/net.git/commit?id=3d0ad09412ffe00c9afa201d01effdb6023d09b4
+
+IPv6 does not allow fragmentation by routers, so there is no
+fragmentation ID in the fixed header.  UFO for IPv6 requires the ID to
+be passed separately, but there is no provision for this in the virtio
+net protocol.
+
+Until recently our software implementation of UFO/IPv6 generated a new
+ID, but this was a bug.  Now we will use ID=0 for any UFO/IPv6 packet
+passed through a tap, which is even worse.
+
+Unfortunately there is no distinction between UFO/IPv4 and v6
+features, so disable UFO on taps and virtio_net completely until we
+have a proper solution.
+
+We cannot depend on VM managers respecting the tap feature flags, so
+keep accepting UFO packets but log a warning the first time we do
+this.
+
+Signed-off-by: Ben Hutchings <ben at decadent.org.uk>
+Fixes: 916e4cf46d02 ("ipv6: reuse ip6_frag_id from ip6_ufo_append_data")
+Signed-off-by: David S. Miller <davem at davemloft.net>
+---
+ drivers/net/macvtap.c    | 13 +++++--------
+ drivers/net/tun.c        | 19 +++++++++++--------
+ drivers/net/virtio_net.c | 24 ++++++++++++++----------
+ 3 files changed, 30 insertions(+), 26 deletions(-)
+
+--- a/drivers/net/macvtap.c
++++ b/drivers/net/macvtap.c
+@@ -65,7 +65,7 @@ static struct cdev macvtap_cdev;
+ static const struct proto_ops macvtap_socket_ops;
+ 
+ #define TUN_OFFLOADS (NETIF_F_HW_CSUM | NETIF_F_TSO_ECN | NETIF_F_TSO | \
+-		      NETIF_F_TSO6 | NETIF_F_UFO)
++		      NETIF_F_TSO6)
+ #define RX_OFFLOADS (NETIF_F_GRO | NETIF_F_LRO)
+ #define TAP_FEATURES (NETIF_F_GSO | NETIF_F_SG)
+ 
+@@ -569,6 +569,8 @@ static int macvtap_skb_from_vnet_hdr(str
+ 			gso_type = SKB_GSO_TCPV6;
+ 			break;
+ 		case VIRTIO_NET_HDR_GSO_UDP:
++			pr_warn_once("macvtap: %s: using disabled UFO feature; please fix this program\n",
++				     current->comm);
+ 			gso_type = SKB_GSO_UDP;
+ 			break;
+ 		default:
+@@ -614,8 +616,6 @@ static void macvtap_skb_to_vnet_hdr(cons
+ 			vnet_hdr->gso_type = VIRTIO_NET_HDR_GSO_TCPV4;
+ 		else if (sinfo->gso_type & SKB_GSO_TCPV6)
+ 			vnet_hdr->gso_type = VIRTIO_NET_HDR_GSO_TCPV6;
+-		else if (sinfo->gso_type & SKB_GSO_UDP)
+-			vnet_hdr->gso_type = VIRTIO_NET_HDR_GSO_UDP;
+ 		else
+ 			BUG();
+ 		if (sinfo->gso_type & SKB_GSO_TCP_ECN)
+@@ -950,9 +950,6 @@ static int set_offload(struct macvtap_qu
+ 			if (arg & TUN_F_TSO6)
+ 				feature_mask |= NETIF_F_TSO6;
+ 		}
+-
+-		if (arg & TUN_F_UFO)
+-			feature_mask |= NETIF_F_UFO;
+ 	}
+ 
+ 	/* tun/tap driver inverts the usage for TSO offloads, where
+@@ -963,7 +960,7 @@ static int set_offload(struct macvtap_qu
+ 	 * When user space turns off TSO, we turn off GSO/LRO so that
+ 	 * user-space will not receive TSO frames.
+ 	 */
+-	if (feature_mask & (NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_UFO))
++	if (feature_mask & (NETIF_F_TSO | NETIF_F_TSO6))
+ 		features |= RX_OFFLOADS;
+ 	else
+ 		features &= ~RX_OFFLOADS;
+@@ -1064,7 +1061,7 @@ static long macvtap_ioctl(struct file *f
+ 	case TUNSETOFFLOAD:
+ 		/* let the user check for future flags */
+ 		if (arg & ~(TUN_F_CSUM | TUN_F_TSO4 | TUN_F_TSO6 |
+-			    TUN_F_TSO_ECN | TUN_F_UFO))
++			    TUN_F_TSO_ECN))
+ 			return -EINVAL;
+ 
+ 		rtnl_lock();
+--- a/drivers/net/tun.c
++++ b/drivers/net/tun.c
+@@ -174,7 +174,7 @@ struct tun_struct {
+ 	struct net_device	*dev;
+ 	netdev_features_t	set_features;
+ #define TUN_USER_FEATURES (NETIF_F_HW_CSUM|NETIF_F_TSO_ECN|NETIF_F_TSO| \
+-			  NETIF_F_TSO6|NETIF_F_UFO)
++			  NETIF_F_TSO6)
+ 
+ 	int			vnet_hdr_sz;
+ 	int			sndbuf;
+@@ -1149,8 +1149,18 @@ static ssize_t tun_get_user(struct tun_s
+ 			skb_shinfo(skb)->gso_type = SKB_GSO_TCPV6;
+ 			break;
+ 		case VIRTIO_NET_HDR_GSO_UDP:
++		{
++			static bool warned;
++
++			if (!warned) {
++				warned = true;
++				netdev_warn(tun->dev,
++					    "%s: using disabled UFO feature; please fix this program\n",
++					    current->comm);
++			}
+ 			skb_shinfo(skb)->gso_type = SKB_GSO_UDP;
+ 			break;
++		}
+ 		default:
+ 			tun->dev->stats.rx_frame_errors++;
+ 			kfree_skb(skb);
+@@ -1251,8 +1261,6 @@ static ssize_t tun_put_user(struct tun_s
+ 				gso.gso_type = VIRTIO_NET_HDR_GSO_TCPV4;
+ 			else if (sinfo->gso_type & SKB_GSO_TCPV6)
+ 				gso.gso_type = VIRTIO_NET_HDR_GSO_TCPV6;
+-			else if (sinfo->gso_type & SKB_GSO_UDP)
+-				gso.gso_type = VIRTIO_NET_HDR_GSO_UDP;
+ 			else {
+ 				pr_err("unexpected GSO type: "
+ 				       "0x%x, gso_size %d, hdr_len %d\n",
+@@ -1761,11 +1769,6 @@ static int set_offload(struct tun_struct
+ 				features |= NETIF_F_TSO6;
+ 			arg &= ~(TUN_F_TSO4|TUN_F_TSO6);
+ 		}
+-
+-		if (arg & TUN_F_UFO) {
+-			features |= NETIF_F_UFO;
+-			arg &= ~TUN_F_UFO;
+-		}
+ 	}
+ 
+ 	/* This gives the user a way to test for new features in future by
+--- a/drivers/net/virtio_net.c
++++ b/drivers/net/virtio_net.c
+@@ -496,8 +496,17 @@ static void receive_buf(struct receive_q
+ 			skb_shinfo(skb)->gso_type = SKB_GSO_TCPV4;
+ 			break;
+ 		case VIRTIO_NET_HDR_GSO_UDP:
++		{
++			static bool warned;
++
++			if (!warned) {
++				warned = true;
++				netdev_warn(dev,
++					    "host using disabled UFO feature; please fix it\n");
++			}
+ 			skb_shinfo(skb)->gso_type = SKB_GSO_UDP;
+ 			break;
++		}
+ 		case VIRTIO_NET_HDR_GSO_TCPV6:
+ 			skb_shinfo(skb)->gso_type = SKB_GSO_TCPV6;
+ 			break;
+@@ -836,8 +845,6 @@ static int xmit_skb(struct send_queue *s
+ 			hdr->hdr.gso_type = VIRTIO_NET_HDR_GSO_TCPV4;
+ 		else if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6)
+ 			hdr->hdr.gso_type = VIRTIO_NET_HDR_GSO_TCPV6;
+-		else if (skb_shinfo(skb)->gso_type & SKB_GSO_UDP)
+-			hdr->hdr.gso_type = VIRTIO_NET_HDR_GSO_UDP;
+ 		else
+ 			BUG();
+ 		if (skb_shinfo(skb)->gso_type & SKB_GSO_TCP_ECN)
+@@ -1657,7 +1664,7 @@ static int virtnet_probe(struct virtio_d
+ 			dev->features |= NETIF_F_HW_CSUM|NETIF_F_SG|NETIF_F_FRAGLIST;
+ 
+ 		if (virtio_has_feature(vdev, VIRTIO_NET_F_GSO)) {
+-			dev->hw_features |= NETIF_F_TSO | NETIF_F_UFO
++			dev->hw_features |= NETIF_F_TSO
+ 				| NETIF_F_TSO_ECN | NETIF_F_TSO6;
+ 		}
+ 		/* Individual feature bits: what can host handle? */
+@@ -1667,11 +1674,9 @@ static int virtnet_probe(struct virtio_d
+ 			dev->hw_features |= NETIF_F_TSO6;
+ 		if (virtio_has_feature(vdev, VIRTIO_NET_F_HOST_ECN))
+ 			dev->hw_features |= NETIF_F_TSO_ECN;
+-		if (virtio_has_feature(vdev, VIRTIO_NET_F_HOST_UFO))
+-			dev->hw_features |= NETIF_F_UFO;
+ 
+ 		if (gso)
+-			dev->features |= dev->hw_features & (NETIF_F_ALL_TSO|NETIF_F_UFO);
++			dev->features |= dev->hw_features & NETIF_F_ALL_TSO;
+ 		/* (!csum && gso) case will be fixed by register_netdev() */
+ 	}
+ 	if (virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_CSUM))
+@@ -1711,8 +1716,7 @@ static int virtnet_probe(struct virtio_d
+ 	/* If we can receive ANY GSO packets, we must allocate large ones. */
+ 	if (virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_TSO4) ||
+ 	    virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_TSO6) ||
+-	    virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_ECN) ||
+-	    virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_UFO))
++	    virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_ECN))
+ 		vi->big_packets = true;
+ 
+ 	if (virtio_has_feature(vdev, VIRTIO_NET_F_MRG_RXBUF))
+@@ -1910,9 +1914,9 @@ static struct virtio_device_id id_table[
+ static unsigned int features[] = {
+ 	VIRTIO_NET_F_CSUM, VIRTIO_NET_F_GUEST_CSUM,
+ 	VIRTIO_NET_F_GSO, VIRTIO_NET_F_MAC,
+-	VIRTIO_NET_F_HOST_TSO4, VIRTIO_NET_F_HOST_UFO, VIRTIO_NET_F_HOST_TSO6,
++	VIRTIO_NET_F_HOST_TSO4, VIRTIO_NET_F_HOST_TSO6,
+ 	VIRTIO_NET_F_HOST_ECN, VIRTIO_NET_F_GUEST_TSO4, VIRTIO_NET_F_GUEST_TSO6,
+-	VIRTIO_NET_F_GUEST_ECN, VIRTIO_NET_F_GUEST_UFO,
++	VIRTIO_NET_F_GUEST_ECN,
+ 	VIRTIO_NET_F_MRG_RXBUF, VIRTIO_NET_F_STATUS, VIRTIO_NET_F_CTRL_VQ,
+ 	VIRTIO_NET_F_CTRL_RX, VIRTIO_NET_F_CTRL_VLAN,
+ 	VIRTIO_NET_F_GUEST_ANNOUNCE, VIRTIO_NET_F_MQ,

Added: dists/sid/linux/debian/patches/bugfix/all/drivers-net-ipv6-Select-IPv6-fragment-idents-for-vir.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/sid/linux/debian/patches/bugfix/all/drivers-net-ipv6-Select-IPv6-fragment-idents-for-vir.patch	Fri Oct 31 02:28:46 2014	(r21998)
@@ -0,0 +1,135 @@
+From: Ben Hutchings <ben at decadent.org.uk>
+Date: Thu, 30 Oct 2014 18:27:17 +0000
+Subject: [2/2] drivers/net, ipv6: Select IPv6 fragment idents for virtio UFO
+ packets
+Origin: https://git.kernel.org/cgit/linux/kernel/git/davem/net.git/commit?id=5188cd44c55db3e92cd9e77a40b5baa7ed4340f7
+
+UFO is now disabled on all drivers that work with virtio net headers,
+but userland may try to send UFO/IPv6 packets anyway.  Instead of
+sending with ID=0, we should select identifiers on their behalf (as we
+used to).
+
+Signed-off-by: Ben Hutchings <ben at decadent.org.uk>
+Fixes: 916e4cf46d02 ("ipv6: reuse ip6_frag_id from ip6_ufo_append_data")
+Signed-off-by: David S. Miller <davem at davemloft.net>
+---
+ drivers/net/macvtap.c  |  3 +++
+ drivers/net/tun.c      |  6 +++++-
+ include/net/ipv6.h     |  2 ++
+ net/ipv6/output_core.c | 34 ++++++++++++++++++++++++++++++++++
+ 4 files changed, 44 insertions(+), 1 deletion(-)
+
+--- a/drivers/net/macvtap.c
++++ b/drivers/net/macvtap.c
+@@ -16,6 +16,7 @@
+ #include <linux/idr.h>
+ #include <linux/fs.h>
+ 
++#include <net/ipv6.h>
+ #include <net/net_namespace.h>
+ #include <net/rtnetlink.h>
+ #include <net/sock.h>
+@@ -572,6 +573,8 @@ static int macvtap_skb_from_vnet_hdr(str
+ 			pr_warn_once("macvtap: %s: using disabled UFO feature; please fix this program\n",
+ 				     current->comm);
+ 			gso_type = SKB_GSO_UDP;
++			if (skb->protocol == htons(ETH_P_IPV6))
++				ipv6_proxy_select_ident(skb);
+ 			break;
+ 		default:
+ 			return -EINVAL;
+--- a/drivers/net/tun.c
++++ b/drivers/net/tun.c
+@@ -65,6 +65,7 @@
+ #include <linux/nsproxy.h>
+ #include <linux/virtio_net.h>
+ #include <linux/rcupdate.h>
++#include <net/ipv6.h>
+ #include <net/net_namespace.h>
+ #include <net/netns/generic.h>
+ #include <net/rtnetlink.h>
+@@ -1139,6 +1140,8 @@ static ssize_t tun_get_user(struct tun_s
+ 		break;
+ 	}
+ 
++	skb_reset_network_header(skb);
++
+ 	if (gso.gso_type != VIRTIO_NET_HDR_GSO_NONE) {
+ 		pr_debug("GSO!\n");
+ 		switch (gso.gso_type & ~VIRTIO_NET_HDR_GSO_ECN) {
+@@ -1159,6 +1162,8 @@ static ssize_t tun_get_user(struct tun_s
+ 					    current->comm);
+ 			}
+ 			skb_shinfo(skb)->gso_type = SKB_GSO_UDP;
++			if (skb->protocol == htons(ETH_P_IPV6))
++				ipv6_proxy_select_ident(skb);
+ 			break;
+ 		}
+ 		default:
+@@ -1189,7 +1194,6 @@ static ssize_t tun_get_user(struct tun_s
+ 		skb_shinfo(skb)->tx_flags |= SKBTX_SHARED_FRAG;
+ 	}
+ 
+-	skb_reset_network_header(skb);
+ 	skb_probe_transport_header(skb, 0);
+ 
+ 	rxhash = skb_get_hash(skb);
+--- a/include/net/ipv6.h
++++ b/include/net/ipv6.h
+@@ -668,6 +668,8 @@ static inline int ipv6_addr_diff(const s
+ 	return __ipv6_addr_diff(a1, a2, sizeof(struct in6_addr));
+ }
+ 
++void ipv6_proxy_select_ident(struct sk_buff *skb);
++
+ int ip6_dst_hoplimit(struct dst_entry *dst);
+ 
+ static inline int ip6_sk_dst_hoplimit(struct ipv6_pinfo *np, struct flowi6 *fl6,
+--- a/net/ipv6/output_core.c
++++ b/net/ipv6/output_core.c
+@@ -3,11 +3,45 @@
+  * not configured or static.  These functions are needed by GSO/GRO implementation.
+  */
+ #include <linux/export.h>
++#include <net/ip.h>
+ #include <net/ipv6.h>
+ #include <net/ip6_fib.h>
+ #include <net/addrconf.h>
+ #include <net/secure_seq.h>
+ 
++/* This function exists only for tap drivers that must support broken
++ * clients requesting UFO without specifying an IPv6 fragment ID.
++ *
++ * This is similar to ipv6_select_ident() but we use an independent hash
++ * seed to limit information leakage.
++ *
++ * The network header must be set before calling this.
++ */
++void ipv6_proxy_select_ident(struct sk_buff *skb)
++{
++	static u32 ip6_proxy_idents_hashrnd __read_mostly;
++	struct in6_addr buf[2];
++	struct in6_addr *addrs;
++	u32 hash, id;
++
++	addrs = skb_header_pointer(skb,
++				   skb_network_offset(skb) +
++				   offsetof(struct ipv6hdr, saddr),
++				   sizeof(buf), buf);
++	if (!addrs)
++		return;
++
++	net_get_random_once(&ip6_proxy_idents_hashrnd,
++			    sizeof(ip6_proxy_idents_hashrnd));
++
++	hash = __ipv6_addr_jhash(&addrs[1], ip6_proxy_idents_hashrnd);
++	hash = __ipv6_addr_jhash(&addrs[0], hash);
++
++	id = ip_idents_reserve(hash, 1);
++	skb_shinfo(skb)->ip6_frag_id = htonl(id);
++}
++EXPORT_SYMBOL_GPL(ipv6_proxy_select_ident);
++
+ int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr)
+ {
+ 	u16 offset = sizeof(struct ipv6hdr);

Modified: dists/sid/linux/debian/patches/series
==============================================================================
--- dists/sid/linux/debian/patches/series	Fri Oct 31 02:23:45 2014	(r21997)
+++ dists/sid/linux/debian/patches/series	Fri Oct 31 02:28:46 2014	(r21998)
@@ -404,3 +404,5 @@
 bugfix/all/HID-i2c-hid-call-the-hid-driver-s-suspend-and-resume.patch
 bugfix/x86/drm-i915-Add-some-L3-registers-to-the-parser-whiteli.patch
 features/all/wireless-rt2x00-add-new-rt2800usb-device.patch
+bugfix/all/drivers-net-Disable-UFO-through-virtio.patch
+bugfix/all/drivers-net-ipv6-Select-IPv6-fragment-idents-for-vir.patch



More information about the Kernel-svn-changes mailing list