netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 0/3] net: minor gso encapsulation fixes
@ 2014-10-20 11:49 Florian Westphal
  2014-10-20 11:49 ` [PATCH v2 1/3] net: gso: use feature flag argument in all protocol gso handlers Florian Westphal
                   ` (3 more replies)
  0 siblings, 4 replies; 5+ messages in thread
From: Florian Westphal @ 2014-10-20 11:49 UTC (permalink / raw)
  To: netdev; +Cc: edumazet, therbert

The following series fixes a minor bug in the gso segmentation handlers
when encapsulation offload is used.

Theoretically this could cause kernel panic when the stack tries
to software-segment such a GRE offload packet, but it looks like there
is only one affected call site (tbf scheduler) and it handles NULL
return value.

I've included a followup patch to add IS_ERR_OR_NULL checks where needed.

While looking into this, I also found that size computation of the individual
segments is incorrect if skb->encapsulation is set.

Please see individual patches for delta vs. v1.

 core/skbuff.c                    |   13 ++++++++++---
 ipv4/af_inet.c                   |    2 +-
 ipv4/gre_offload.c               |    2 +-
 ipv4/ip_output.c                 |    2 +-
 ipv4/udp_offload.c               |    2 +-
 ipv6/ip6_offload.c               |    2 +-
 mpls/mpls_gso.c                  |    2 +-
 netfilter/nfnetlink_queue_core.c |    2 +-
 openvswitch/datapath.c           |    2 ++
 xfrm/xfrm_output.c               |    2 ++
 10 files changed, 21 insertions(+), 10 deletions(-)

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH v2 1/3] net: gso: use feature flag argument in all protocol gso handlers
  2014-10-20 11:49 [PATCH v2 0/3] net: minor gso encapsulation fixes Florian Westphal
@ 2014-10-20 11:49 ` Florian Westphal
  2014-10-20 11:49 ` [PATCH v2 2/3] net: make skb_gso_segment error handling more robust Florian Westphal
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 5+ messages in thread
From: Florian Westphal @ 2014-10-20 11:49 UTC (permalink / raw)
  To: netdev; +Cc: edumazet, therbert, Florian Westphal, Pravin B Shelar

skb_gso_segment() has a 'features' argument representing offload features
available to the output path.

A few handlers, e.g. GRE, instead re-fetch the features of skb->dev and use
those instead of the provided ones when handing encapsulation/tunnels.

Depending on dev->hw_enc_features of the output device skb_gso_segment() can
then return NULL even when the caller has disabled all GSO feature bits,
as segmentation of inner header thinks device will take care of segmentation.

This e.g. affects the tbf scheduler, which will silently drop GRE-encap GSO skbs
that did not fit the remaining token quota as the segmentation does not work
when device supports corresponding hw offload capabilities.

Cc: Pravin B Shelar <pshelar@nicira.com>
Signed-off-by: Florian Westphal <fw@strlen.de>
---
 No changes since v1.

 net/ipv4/af_inet.c     | 2 +-
 net/ipv4/gre_offload.c | 2 +-
 net/ipv4/udp_offload.c | 2 +-
 net/ipv6/ip6_offload.c | 2 +-
 net/mpls/mpls_gso.c    | 2 +-
 5 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index 92db7a6..8b7fe5b 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -1246,7 +1246,7 @@ static struct sk_buff *inet_gso_segment(struct sk_buff *skb,
 
 	encap = SKB_GSO_CB(skb)->encap_level > 0;
 	if (encap)
-		features = skb->dev->hw_enc_features & netif_skb_features(skb);
+		features &= skb->dev->hw_enc_features;
 	SKB_GSO_CB(skb)->encap_level += ihl;
 
 	skb_reset_transport_header(skb);
diff --git a/net/ipv4/gre_offload.c b/net/ipv4/gre_offload.c
index ccda096..f6e345c 100644
--- a/net/ipv4/gre_offload.c
+++ b/net/ipv4/gre_offload.c
@@ -68,7 +68,7 @@ static struct sk_buff *gre_gso_segment(struct sk_buff *skb,
 	skb->mac_len = skb_inner_network_offset(skb);
 
 	/* segment inner packet. */
-	enc_features = skb->dev->hw_enc_features & netif_skb_features(skb);
+	enc_features = skb->dev->hw_enc_features & features;
 	segs = skb_mac_gso_segment(skb, enc_features);
 	if (IS_ERR_OR_NULL(segs)) {
 		skb_gso_error_unwind(skb, protocol, ghl, mac_offset, mac_len);
diff --git a/net/ipv4/udp_offload.c b/net/ipv4/udp_offload.c
index 507310e..6480cea 100644
--- a/net/ipv4/udp_offload.c
+++ b/net/ipv4/udp_offload.c
@@ -58,7 +58,7 @@ static struct sk_buff *__skb_udp_tunnel_segment(struct sk_buff *skb,
 		skb->encap_hdr_csum = 1;
 
 	/* segment inner packet. */
-	enc_features = skb->dev->hw_enc_features & netif_skb_features(skb);
+	enc_features = skb->dev->hw_enc_features & features;
 	segs = gso_inner_segment(skb, enc_features);
 	if (IS_ERR_OR_NULL(segs)) {
 		skb_gso_error_unwind(skb, protocol, tnl_hlen, mac_offset,
diff --git a/net/ipv6/ip6_offload.c b/net/ipv6/ip6_offload.c
index 91014d3..a071563 100644
--- a/net/ipv6/ip6_offload.c
+++ b/net/ipv6/ip6_offload.c
@@ -90,7 +90,7 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb,
 
 	encap = SKB_GSO_CB(skb)->encap_level > 0;
 	if (encap)
-		features = skb->dev->hw_enc_features & netif_skb_features(skb);
+		features &= skb->dev->hw_enc_features;
 	SKB_GSO_CB(skb)->encap_level += sizeof(*ipv6h);
 
 	ipv6h = ipv6_hdr(skb);
diff --git a/net/mpls/mpls_gso.c b/net/mpls/mpls_gso.c
index e28ed2e..f0f5309 100644
--- a/net/mpls/mpls_gso.c
+++ b/net/mpls/mpls_gso.c
@@ -48,7 +48,7 @@ static struct sk_buff *mpls_gso_segment(struct sk_buff *skb,
 	__skb_push(skb, skb->mac_len);
 
 	/* Segment inner packet. */
-	mpls_features = skb->dev->mpls_features & netif_skb_features(skb);
+	mpls_features = skb->dev->mpls_features & features;
 	segs = skb_mac_gso_segment(skb, mpls_features);
 
 
-- 
2.0.4

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH v2 2/3] net: make skb_gso_segment error handling more robust
  2014-10-20 11:49 [PATCH v2 0/3] net: minor gso encapsulation fixes Florian Westphal
  2014-10-20 11:49 ` [PATCH v2 1/3] net: gso: use feature flag argument in all protocol gso handlers Florian Westphal
@ 2014-10-20 11:49 ` Florian Westphal
  2014-10-20 11:49 ` [PATCH v2 3/3] net: core: handle encapsulation offloads when computing segment lengths Florian Westphal
  2014-10-20 18:04 ` [PATCH v2 0/3] net: minor gso encapsulation fixes David Miller
  3 siblings, 0 replies; 5+ messages in thread
From: Florian Westphal @ 2014-10-20 11:49 UTC (permalink / raw)
  To: netdev; +Cc: edumazet, therbert, Florian Westphal

skb_gso_segment has three possible return values:
1. a pointer to the first segmented skb
2. an errno value (IS_ERR())
3. NULL.  This can happen when GSO is used for header verification.

However, several callers currently test IS_ERR instead of IS_ERR_OR_NULL
and would oops when NULL is returned.

Note that these call sites should never actually see such a NULL return
value; all callers mask out the GSO bits in the feature argument.

However, there have been issues with some protocol handlers erronously not
respecting the specified feature mask in some cases.

It is preferable to get 'have to turn off hw offloading, else slow' reports
rather than 'kernel crashes'.

Signed-off-by: Florian Westphal <fw@strlen.de>
---
 Changes since v1:
  - don't return PTR_ERR(NULL).
  - update changelog to clarify that segs == NULL 'should not happen'.

 net/ipv4/ip_output.c                 | 2 +-
 net/netfilter/nfnetlink_queue_core.c | 2 +-
 net/openvswitch/datapath.c           | 2 ++
 net/xfrm/xfrm_output.c               | 2 ++
 4 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
index 88e5ef2..bc6471d 100644
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@ -231,7 +231,7 @@ static int ip_finish_output_gso(struct sk_buff *skb)
 	 */
 	features = netif_skb_features(skb);
 	segs = skb_gso_segment(skb, features & ~NETIF_F_GSO_MASK);
-	if (IS_ERR(segs)) {
+	if (IS_ERR_OR_NULL(segs)) {
 		kfree_skb(skb);
 		return -ENOMEM;
 	}
diff --git a/net/netfilter/nfnetlink_queue_core.c b/net/netfilter/nfnetlink_queue_core.c
index a82077d..7c60ccd 100644
--- a/net/netfilter/nfnetlink_queue_core.c
+++ b/net/netfilter/nfnetlink_queue_core.c
@@ -665,7 +665,7 @@ nfqnl_enqueue_packet(struct nf_queue_entry *entry, unsigned int queuenum)
 	 * returned by nf_queue.  For instance, callers rely on -ECANCELED to
 	 * mean 'ignore this hook'.
 	 */
-	if (IS_ERR(segs))
+	if (IS_ERR_OR_NULL(segs))
 		goto out_err;
 	queued = 0;
 	err = 0;
diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c
index 2e31d9e..e6d7255 100644
--- a/net/openvswitch/datapath.c
+++ b/net/openvswitch/datapath.c
@@ -324,6 +324,8 @@ static int queue_gso_packets(struct datapath *dp, struct sk_buff *skb,
 	segs = __skb_gso_segment(skb, NETIF_F_SG, false);
 	if (IS_ERR(segs))
 		return PTR_ERR(segs);
+	if (segs == NULL)
+		return -EINVAL;
 
 	/* Queue all of the segments. */
 	skb = segs;
diff --git a/net/xfrm/xfrm_output.c b/net/xfrm/xfrm_output.c
index 499d6c1..7c53285 100644
--- a/net/xfrm/xfrm_output.c
+++ b/net/xfrm/xfrm_output.c
@@ -157,6 +157,8 @@ static int xfrm_output_gso(struct sk_buff *skb)
 	kfree_skb(skb);
 	if (IS_ERR(segs))
 		return PTR_ERR(segs);
+	if (segs == NULL)
+		return -EINVAL;
 
 	do {
 		struct sk_buff *nskb = segs->next;
-- 
2.0.4

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH v2 3/3] net: core: handle encapsulation offloads when computing segment lengths
  2014-10-20 11:49 [PATCH v2 0/3] net: minor gso encapsulation fixes Florian Westphal
  2014-10-20 11:49 ` [PATCH v2 1/3] net: gso: use feature flag argument in all protocol gso handlers Florian Westphal
  2014-10-20 11:49 ` [PATCH v2 2/3] net: make skb_gso_segment error handling more robust Florian Westphal
@ 2014-10-20 11:49 ` Florian Westphal
  2014-10-20 18:04 ` [PATCH v2 0/3] net: minor gso encapsulation fixes David Miller
  3 siblings, 0 replies; 5+ messages in thread
From: Florian Westphal @ 2014-10-20 11:49 UTC (permalink / raw)
  To: netdev; +Cc: edumazet, therbert, Florian Westphal

if ->encapsulation is set we have to use inner_tcp_hdrlen and add the
size of the inner network headers too.

This is 'mostly harmless'; tbf might send skb that is slightly over
quota or drop skb even if it would have fit.

Signed-off-by: Florian Westphal <fw@strlen.de>
---
 No changes since v1.

 net/core/skbuff.c | 13 ++++++++++---
 1 file changed, 10 insertions(+), 3 deletions(-)

diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 61059a0..c16615b 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -4070,15 +4070,22 @@ EXPORT_SYMBOL_GPL(skb_scrub_packet);
 unsigned int skb_gso_transport_seglen(const struct sk_buff *skb)
 {
 	const struct skb_shared_info *shinfo = skb_shinfo(skb);
+	unsigned int thlen = 0;
 
-	if (likely(shinfo->gso_type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6)))
-		return tcp_hdrlen(skb) + shinfo->gso_size;
+	if (skb->encapsulation) {
+		thlen = skb_inner_transport_header(skb) -
+			skb_transport_header(skb);
 
+		if (likely(shinfo->gso_type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6)))
+			thlen += inner_tcp_hdrlen(skb);
+	} else if (likely(shinfo->gso_type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6))) {
+		thlen = tcp_hdrlen(skb);
+	}
 	/* UFO sets gso_size to the size of the fragmentation
 	 * payload, i.e. the size of the L4 (UDP) header is already
 	 * accounted for.
 	 */
-	return shinfo->gso_size;
+	return thlen + shinfo->gso_size;
 }
 EXPORT_SYMBOL_GPL(skb_gso_transport_seglen);
 
-- 
2.0.4

^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH v2 0/3] net: minor gso encapsulation fixes
  2014-10-20 11:49 [PATCH v2 0/3] net: minor gso encapsulation fixes Florian Westphal
                   ` (2 preceding siblings ...)
  2014-10-20 11:49 ` [PATCH v2 3/3] net: core: handle encapsulation offloads when computing segment lengths Florian Westphal
@ 2014-10-20 18:04 ` David Miller
  3 siblings, 0 replies; 5+ messages in thread
From: David Miller @ 2014-10-20 18:04 UTC (permalink / raw)
  To: fw; +Cc: netdev, edumazet, therbert

From: Florian Westphal <fw@strlen.de>
Date: Mon, 20 Oct 2014 13:49:15 +0200

> The following series fixes a minor bug in the gso segmentation handlers
> when encapsulation offload is used.
> 
> Theoretically this could cause kernel panic when the stack tries
> to software-segment such a GRE offload packet, but it looks like there
> is only one affected call site (tbf scheduler) and it handles NULL
> return value.
> 
> I've included a followup patch to add IS_ERR_OR_NULL checks where needed.
> 
> While looking into this, I also found that size computation of the individual
> segments is incorrect if skb->encapsulation is set.
> 
> Please see individual patches for delta vs. v1.

Series applied, thanks Florian.

Longer term I'd really like to see the ops->gso_segment() implementations not
return NULL, but rather locally determinned pointer error codes instead.

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2014-10-20 18:04 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-10-20 11:49 [PATCH v2 0/3] net: minor gso encapsulation fixes Florian Westphal
2014-10-20 11:49 ` [PATCH v2 1/3] net: gso: use feature flag argument in all protocol gso handlers Florian Westphal
2014-10-20 11:49 ` [PATCH v2 2/3] net: make skb_gso_segment error handling more robust Florian Westphal
2014-10-20 11:49 ` [PATCH v2 3/3] net: core: handle encapsulation offloads when computing segment lengths Florian Westphal
2014-10-20 18:04 ` [PATCH v2 0/3] net: minor gso encapsulation fixes David Miller

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).