aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBen Hutchings <bhutchings@solarflare.com>2012-07-30 11:57:00 -0400
committerDavid S. Miller <davem@davemloft.net>2012-08-02 03:19:17 -0400
commit30b678d844af3305cda5953467005cebb5d7b687 (patch)
tree8e57f081d3a8f8dc44630cee223d2b45ec196e5e
parent1a9b4993b70fb1884716902774dc9025b457760d (diff)
net: Allow driver to limit number of GSO segments per skb
A peer (or local user) may cause TCP to use a nominal MSS of as little as 88 (actual MSS of 76 with timestamps). Given that we have a sufficiently prodigious local sender and the peer ACKs quickly enough, it is nevertheless possible to grow the window for such a connection to the point that we will try to send just under 64K at once. This results in a single skb that expands to 861 segments. In some drivers with TSO support, such an skb will require hundreds of DMA descriptors; a substantial fraction of a TX ring or even more than a full ring. The TX queue selected for the skb may stall and trigger the TX watchdog repeatedly (since the problem skb will be retried after the TX reset). This particularly affects sfc, for which the issue is designated as CVE-2012-3412. Therefore: 1. Add the field net_device::gso_max_segs holding the device-specific limit. 2. In netif_skb_features(), if the number of segments is too high then mask out GSO features to force fall back to software GSO. Signed-off-by: Ben Hutchings <bhutchings@solarflare.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/linux/netdevice.h2
-rw-r--r--net/core/dev.c4
2 files changed, 6 insertions, 0 deletions
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index eb06e58bed0b..a9db4f33407f 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -1300,6 +1300,8 @@ struct net_device {
1300 /* for setting kernel sock attribute on TCP connection setup */ 1300 /* for setting kernel sock attribute on TCP connection setup */
1301#define GSO_MAX_SIZE 65536 1301#define GSO_MAX_SIZE 65536
1302 unsigned int gso_max_size; 1302 unsigned int gso_max_size;
1303#define GSO_MAX_SEGS 65535
1304 u16 gso_max_segs;
1303 1305
1304#ifdef CONFIG_DCB 1306#ifdef CONFIG_DCB
1305 /* Data Center Bridging netlink ops */ 1307 /* Data Center Bridging netlink ops */
diff --git a/net/core/dev.c b/net/core/dev.c
index 0cb3fe8d8e72..f91abf800161 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -2134,6 +2134,9 @@ netdev_features_t netif_skb_features(struct sk_buff *skb)
2134 __be16 protocol = skb->protocol; 2134 __be16 protocol = skb->protocol;
2135 netdev_features_t features = skb->dev->features; 2135 netdev_features_t features = skb->dev->features;
2136 2136
2137 if (skb_shinfo(skb)->gso_segs > skb->dev->gso_max_segs)
2138 features &= ~NETIF_F_GSO_MASK;
2139
2137 if (protocol == htons(ETH_P_8021Q)) { 2140 if (protocol == htons(ETH_P_8021Q)) {
2138 struct vlan_ethhdr *veh = (struct vlan_ethhdr *)skb->data; 2141 struct vlan_ethhdr *veh = (struct vlan_ethhdr *)skb->data;
2139 protocol = veh->h_vlan_encapsulated_proto; 2142 protocol = veh->h_vlan_encapsulated_proto;
@@ -5986,6 +5989,7 @@ struct net_device *alloc_netdev_mqs(int sizeof_priv, const char *name,
5986 dev_net_set(dev, &init_net); 5989 dev_net_set(dev, &init_net);
5987 5990
5988 dev->gso_max_size = GSO_MAX_SIZE; 5991 dev->gso_max_size = GSO_MAX_SIZE;
5992 dev->gso_max_segs = GSO_MAX_SEGS;
5989 5993
5990 INIT_LIST_HEAD(&dev->napi_list); 5994 INIT_LIST_HEAD(&dev->napi_list);
5991 INIT_LIST_HEAD(&dev->unreg_list); 5995 INIT_LIST_HEAD(&dev->unreg_list);