netfilter-devel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] core, nfqueue, openvswitch: Orphan frags in skb_zerocopy and handle errors
@ 2014-03-18 21:17 Zoltan Kiss
       [not found] ` <1395177455-2077-1-git-send-email-zoltan.kiss-Sxgqhf6Nn4DQT0dZR+AlfA@public.gmane.org>
  0 siblings, 1 reply; 6+ messages in thread
From: Zoltan Kiss @ 2014-03-18 21:17 UTC (permalink / raw)
  To: Jesse Gross, pshelar-l0M0P4e3n4LQT0dZR+AlfA,
	tgraf-H+wXaHxf7aLQT0dZR+AlfA, dev-yBygre7rU0TnMu66kgdUjQ
  Cc: netfilter-u79uwXL29TY76Z2rM5mHXA, Miklos Szeredi,
	kvm-u79uwXL29TY76Z2rM5mHXA, Michael S. Tsirkin, Jason Wang,
	Eric Dumazet, Jan Beulich, Tom Herbert, Herbert Xu,
	coreteam-Cap9r6Oaw4JrovVCs/uTlw, Jozsef Kadlecsik,
	xen-devel-GuqFBffKawtpuQazS67q72D2FQJk+8+b, Pablo Neira Ayuso,
	Jiri Pirko, Paul Durrant, netdev-u79uwXL29TY76Z2rM5mHXA,
	Florian Westphal, linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	David S. Miller, Daniel Borkmann,
	netfilter-devel-u79uwXL29TY76Z2rM5mHXA, Joe Perches,
	Patrick McHardy

skb_zerocopy can copy elements of the frags array between skbs, but it doesn't
orphan them. Also, it doesn't handle errors, so this patch takes care of that
as well.

Signed-off-by: Zoltan Kiss <zoltan.kiss-Sxgqhf6Nn4DQT0dZR+AlfA@public.gmane.org>
---
 net/openvswitch/datapath.c |    6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 03db95a..35c4e85 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -2508,8 +2508,8 @@ int skb_splice_bits(struct sk_buff *skb, unsigned int offset,
 		    unsigned int flags);
 void skb_copy_and_csum_dev(const struct sk_buff *skb, u8 *to);
 unsigned int skb_zerocopy_headlen(const struct sk_buff *from);
-void skb_zerocopy(struct sk_buff *to, const struct sk_buff *from,
-		  int len, int hlen);
+int skb_zerocopy(struct sk_buff *to, const struct sk_buff *from,
+		 int len, int hlen);
 void skb_split(struct sk_buff *skb, struct sk_buff *skb1, const u32 len);
 int skb_shift(struct sk_buff *tgt, struct sk_buff *skb, int shiftlen);
 void skb_scrub_packet(struct sk_buff *skb, bool xnet);
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 3f14c63..60f623c 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -2127,25 +2127,36 @@ EXPORT_SYMBOL_GPL(skb_zerocopy_headlen);
  *
  *	The `hlen` as calculated by skb_zerocopy_headlen() specifies the
  *	headroom in the `to` buffer.
+ *
+ *	Return value:
+ *	0: everything is OK
+ *	-ENOMEM: couldn't orphan frags of from due to lack of memory
+ *	-EFAULT: skb_copy_bits() found some problem with geometry
  */
-void
+int
 skb_zerocopy(struct sk_buff *to, const struct sk_buff *from, int len, int hlen)
 {
 	int i, j = 0;
 	int plen = 0; /* length of skb->head fragment */
+	int ret;
 	struct page *page;
 	unsigned int offset;
 
 	BUG_ON(!from->head_frag && !hlen);
 
 	/* dont bother with small payloads */
-	if (len <= skb_tailroom(to)) {
-		skb_copy_bits(from, 0, skb_put(to, len), len);
-		return;
+	if (len <= skb_tailroom(to))
+		return skb_copy_bits(from, 0, skb_put(to, len), len);
+
+	if (unlikely(skb_orphan_frags(to, GFP_ATOMIC))) {
+		skb_tx_error(to);
+		return -ENOMEM;
 	}
 
 	if (hlen) {
-		skb_copy_bits(from, 0, skb_put(to, hlen), hlen);
+		ret = skb_copy_bits(from, 0, skb_put(to, hlen), hlen);
+		if (unlikely(ret))
+			return ret;
 		len -= hlen;
 	} else {
 		plen = min_t(int, skb_headlen(from), len);
@@ -2173,6 +2184,8 @@ skb_zerocopy(struct sk_buff *to, const struct sk_buff *from, int len, int hlen)
 		j++;
 	}
 	skb_shinfo(to)->nr_frags = j;
+
+	return 0;
 }
 EXPORT_SYMBOL_GPL(skb_zerocopy);
 
diff --git a/net/netfilter/nfnetlink_queue_core.c b/net/netfilter/nfnetlink_queue_core.c
index f072fe8..ea02d16 100644
--- a/net/netfilter/nfnetlink_queue_core.c
+++ b/net/netfilter/nfnetlink_queue_core.c
@@ -488,7 +488,8 @@ nfqnl_build_packet_message(struct net *net, struct nfqnl_instance *queue,
 		nla->nla_type = NFQA_PAYLOAD;
 		nla->nla_len = nla_attr_size(data_len);
 
-		skb_zerocopy(skb, entskb, data_len, hlen);
+		if (skb_zerocopy(skb, entskb, data_len, hlen))
+			goto nla_put_failure;
 	}
 
 	nlh->nlmsg_len = skb->len;
diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c
index c53fe0c..9a9f668 100644
--- a/net/openvswitch/datapath.c
+++ b/net/openvswitch/datapath.c
@@ -464,7 +464,9 @@ static int queue_userspace_packet(struct datapath *dp, struct sk_buff *skb,
 	}
 	nla->nla_len = nla_attr_size(skb->len);
 
-	skb_zerocopy(user_skb, skb, skb->len, hlen);
+	err = skb_zerocopy(user_skb, skb, skb->len, hlen);
+	if (err)
+		goto out;
 
 	/* Pad OVS_PACKET_ATTR_PACKET if linear copy was performed */
 	if (!(dp->user_features & OVS_DP_F_UNALIGNED)) {

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

* Re: [PATCH] core, nfqueue, openvswitch: Orphan frags in skb_zerocopy and handle errors
       [not found] ` <1395177455-2077-1-git-send-email-zoltan.kiss-Sxgqhf6Nn4DQT0dZR+AlfA@public.gmane.org>
@ 2014-03-19 20:24   ` David Miller
  2014-03-19 20:39     ` Zoltan Kiss
  0 siblings, 1 reply; 6+ messages in thread
From: David Miller @ 2014-03-19 20:24 UTC (permalink / raw)
  To: zoltan.kiss-Sxgqhf6Nn4DQT0dZR+AlfA
  Cc: netfilter-u79uwXL29TY76Z2rM5mHXA, mszeredi-AlSwsSmVLrQ,
	kvm-u79uwXL29TY76Z2rM5mHXA, mst-H+wXaHxf7aLQT0dZR+AlfA,
	jasowang-H+wXaHxf7aLQT0dZR+AlfA, edumazet-hpIqsD4AKlfQT0dZR+AlfA,
	JBeulich-IBi9RG/b67k, therbert-hpIqsD4AKlfQT0dZR+AlfA,
	dev-yBygre7rU0TnMu66kgdUjQ,
	herbert-lOAM2aK0SrRLBo1qDEOMRrpzq4S04n8Q,
	coreteam-Cap9r6Oaw4JrovVCs/uTlw,
	kadlec-K40Dz/62t/MgiyqX0sVFJYdd74u8MsAO,
	xen-devel-GuqFBffKawtpuQazS67q72D2FQJk+8+b,
	pablo-Cap9r6Oaw4JrovVCs/uTlw, jiri-rHqAuBHg3fBzbRFIqnYvSA,
	Paul.Durrant-Sxgqhf6Nn4DQT0dZR+AlfA,
	netdev-u79uwXL29TY76Z2rM5mHXA, fw-HFFVJYpyMKqzQB+pC5nmwQ,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	dborkman-H+wXaHxf7aLQT0dZR+AlfA,
	netfilter-devel-u79uwXL29TY76Z2rM5mHXA,
	joe-6d6DIl74uiNBDgjK7y7TUQ, kaber-dcUjhNyLwpNeoWH0uzbU5w

From: Zoltan Kiss <zoltan.kiss-Sxgqhf6Nn4DQT0dZR+AlfA@public.gmane.org>
Date: Tue, 18 Mar 2014 21:17:35 +0000

> skb_zerocopy can copy elements of the frags array between skbs, but it doesn't
> orphan them. Also, it doesn't handle errors, so this patch takes care of that
> as well.
> 
> Signed-off-by: Zoltan Kiss <zoltan.kiss-Sxgqhf6Nn4DQT0dZR+AlfA@public.gmane.org>
> ---
>  net/openvswitch/datapath.c |    6 ++++++

Something is seriously wrong with the diffstat generated for
your submission, please fix this and resubmit.

Thank you.

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

* [PATCH] core, nfqueue, openvswitch: Orphan frags in skb_zerocopy and handle errors
@ 2014-03-19 20:38 Zoltan Kiss
       [not found] ` <1395261516-305-1-git-send-email-zoltan.kiss-Sxgqhf6Nn4DQT0dZR+AlfA@public.gmane.org>
  0 siblings, 1 reply; 6+ messages in thread
From: Zoltan Kiss @ 2014-03-19 20:38 UTC (permalink / raw)
  To: Jesse Gross, pshelar-l0M0P4e3n4LQT0dZR+AlfA,
	tgraf-H+wXaHxf7aLQT0dZR+AlfA, dev-yBygre7rU0TnMu66kgdUjQ
  Cc: netfilter-u79uwXL29TY76Z2rM5mHXA, Miklos Szeredi,
	kvm-u79uwXL29TY76Z2rM5mHXA, Michael S. Tsirkin, Jason Wang,
	Eric Dumazet, Jan Beulich, Tom Herbert, Herbert Xu,
	coreteam-Cap9r6Oaw4JrovVCs/uTlw, Jozsef Kadlecsik,
	xen-devel-GuqFBffKawtpuQazS67q72D2FQJk+8+b, Pablo Neira Ayuso,
	Jiri Pirko, Paul Durrant, netdev-u79uwXL29TY76Z2rM5mHXA,
	Florian Westphal, linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	David S. Miller, Daniel Borkmann,
	netfilter-devel-u79uwXL29TY76Z2rM5mHXA, Joe Perches,
	Patrick McHardy

skb_zerocopy can copy elements of the frags array between skbs, but it doesn't
orphan them. Also, it doesn't handle errors, so this patch takes care of that
as well.

Signed-off-by: Zoltan Kiss <zoltan.kiss-Sxgqhf6Nn4DQT0dZR+AlfA@public.gmane.org>
---
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 03db95a..35c4e85 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -2508,8 +2508,8 @@ int skb_splice_bits(struct sk_buff *skb, unsigned int offset,
 		    unsigned int flags);
 void skb_copy_and_csum_dev(const struct sk_buff *skb, u8 *to);
 unsigned int skb_zerocopy_headlen(const struct sk_buff *from);
-void skb_zerocopy(struct sk_buff *to, const struct sk_buff *from,
-		  int len, int hlen);
+int skb_zerocopy(struct sk_buff *to, const struct sk_buff *from,
+		 int len, int hlen);
 void skb_split(struct sk_buff *skb, struct sk_buff *skb1, const u32 len);
 int skb_shift(struct sk_buff *tgt, struct sk_buff *skb, int shiftlen);
 void skb_scrub_packet(struct sk_buff *skb, bool xnet);
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 3f14c63..60f623c 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -2127,25 +2127,36 @@ EXPORT_SYMBOL_GPL(skb_zerocopy_headlen);
  *
  *	The `hlen` as calculated by skb_zerocopy_headlen() specifies the
  *	headroom in the `to` buffer.
+ *
+ *	Return value:
+ *	0: everything is OK
+ *	-ENOMEM: couldn't orphan frags of from due to lack of memory
+ *	-EFAULT: skb_copy_bits() found some problem with geometry
  */
-void
+int
 skb_zerocopy(struct sk_buff *to, const struct sk_buff *from, int len, int hlen)
 {
 	int i, j = 0;
 	int plen = 0; /* length of skb->head fragment */
+	int ret;
 	struct page *page;
 	unsigned int offset;
 
 	BUG_ON(!from->head_frag && !hlen);
 
 	/* dont bother with small payloads */
-	if (len <= skb_tailroom(to)) {
-		skb_copy_bits(from, 0, skb_put(to, len), len);
-		return;
+	if (len <= skb_tailroom(to))
+		return skb_copy_bits(from, 0, skb_put(to, len), len);
+
+	if (unlikely(skb_orphan_frags(to, GFP_ATOMIC))) {
+		skb_tx_error(to);
+		return -ENOMEM;
 	}
 
 	if (hlen) {
-		skb_copy_bits(from, 0, skb_put(to, hlen), hlen);
+		ret = skb_copy_bits(from, 0, skb_put(to, hlen), hlen);
+		if (unlikely(ret))
+			return ret;
 		len -= hlen;
 	} else {
 		plen = min_t(int, skb_headlen(from), len);
@@ -2173,6 +2184,8 @@ skb_zerocopy(struct sk_buff *to, const struct sk_buff *from, int len, int hlen)
 		j++;
 	}
 	skb_shinfo(to)->nr_frags = j;
+
+	return 0;
 }
 EXPORT_SYMBOL_GPL(skb_zerocopy);
 
diff --git a/net/netfilter/nfnetlink_queue_core.c b/net/netfilter/nfnetlink_queue_core.c
index f072fe8..ea02d16 100644
--- a/net/netfilter/nfnetlink_queue_core.c
+++ b/net/netfilter/nfnetlink_queue_core.c
@@ -488,7 +488,8 @@ nfqnl_build_packet_message(struct net *net, struct nfqnl_instance *queue,
 		nla->nla_type = NFQA_PAYLOAD;
 		nla->nla_len = nla_attr_size(data_len);
 
-		skb_zerocopy(skb, entskb, data_len, hlen);
+		if (skb_zerocopy(skb, entskb, data_len, hlen))
+			goto nla_put_failure;
 	}
 
 	nlh->nlmsg_len = skb->len;
diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c
index c53fe0c..9a9f668 100644
--- a/net/openvswitch/datapath.c
+++ b/net/openvswitch/datapath.c
@@ -464,7 +464,9 @@ static int queue_userspace_packet(struct datapath *dp, struct sk_buff *skb,
 	}
 	nla->nla_len = nla_attr_size(skb->len);
 
-	skb_zerocopy(user_skb, skb, skb->len, hlen);
+	err = skb_zerocopy(user_skb, skb, skb->len, hlen);
+	if (err)
+		goto out;
 
 	/* Pad OVS_PACKET_ATTR_PACKET if linear copy was performed */
 	if (!(dp->user_features & OVS_DP_F_UNALIGNED)) {

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

* Re: [PATCH] core, nfqueue, openvswitch: Orphan frags in skb_zerocopy and handle errors
  2014-03-19 20:24   ` David Miller
@ 2014-03-19 20:39     ` Zoltan Kiss
  0 siblings, 0 replies; 6+ messages in thread
From: Zoltan Kiss @ 2014-03-19 20:39 UTC (permalink / raw)
  To: David Miller
  Cc: jesse, pshelar, tgraf, dev, pablo, kaber, kadlec, edumazet,
	dborkman, therbert, jasowang, fw, joe, horms, jiri, mst,
	Paul.Durrant, JBeulich, herbert, mszeredi, netfilter-devel,
	netfilter, coreteam, xen-devel, netdev, linux-kernel, kvm

On 19/03/14 20:24, David Miller wrote:
> From: Zoltan Kiss <zoltan.kiss@citrix.com>
> Date: Tue, 18 Mar 2014 21:17:35 +0000
>
>> skb_zerocopy can copy elements of the frags array between skbs, but it doesn't
>> orphan them. Also, it doesn't handle errors, so this patch takes care of that
>> as well.
>>
>> Signed-off-by: Zoltan Kiss <zoltan.kiss@citrix.com>
>> ---
>>   net/openvswitch/datapath.c |    6 ++++++
>
> Something is seriously wrong with the diffstat generated for
> your submission, please fix this and resubmit.

Sorry, I've turned off diffstat in guilt a while ago, but this patch had 
an old version of it. I've resent it.

Zoli

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

* Re: [PATCH] core, nfqueue, openvswitch: Orphan frags in skb_zerocopy and handle errors
       [not found] ` <1395261516-305-1-git-send-email-zoltan.kiss-Sxgqhf6Nn4DQT0dZR+AlfA@public.gmane.org>
@ 2014-03-19 20:47   ` Thomas Graf
       [not found]     ` <532A026E.5070609-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
  0 siblings, 1 reply; 6+ messages in thread
From: Thomas Graf @ 2014-03-19 20:47 UTC (permalink / raw)
  To: Zoltan Kiss, Jesse Gross, pshelar-l0M0P4e3n4LQT0dZR+AlfA,
	dev-yBygre7rU0TnMu66kgdUjQ
  Cc: netfilter-u79uwXL29TY76Z2rM5mHXA, Miklos Szeredi,
	kvm-u79uwXL29TY76Z2rM5mHXA, Michael S. Tsirkin, Jason Wang,
	Eric Dumazet, Jan Beulich, Tom Herbert, Herbert Xu,
	coreteam-Cap9r6Oaw4JrovVCs/uTlw, Jozsef Kadlecsik,
	xen-devel-GuqFBffKawtpuQazS67q72D2FQJk+8+b, Pablo Neira Ayuso,
	Jiri Pirko, Paul Durrant, netdev-u79uwXL29TY76Z2rM5mHXA,
	Florian Westphal, linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	David S. Miller, Daniel Borkmann,
	netfilter-devel-u79uwXL29TY76Z2rM5mHXA, Joe Perches,
	Patrick McHardy

On 03/19/2014 09:38 PM, Zoltan Kiss wrote:
> skb_zerocopy can copy elements of the frags array between skbs, but it doesn't
> orphan them. Also, it doesn't handle errors, so this patch takes care of that
> as well.
>
> Signed-off-by: Zoltan Kiss <zoltan.kiss-Sxgqhf6Nn4DQT0dZR+AlfA@public.gmane.org>
> ---

> +	if (unlikely(skb_orphan_frags(to, GFP_ATOMIC))) {
> +		skb_tx_error(to);
> +		return -ENOMEM;
>   	}

I think you should move this down to right before we iterate over the
frags.

Looks good otherwise.

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

* Re: [PATCH] core, nfqueue, openvswitch: Orphan frags in skb_zerocopy and handle errors
       [not found]     ` <532A026E.5070609-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
@ 2014-03-19 21:07       ` Zoltan Kiss
  0 siblings, 0 replies; 6+ messages in thread
From: Zoltan Kiss @ 2014-03-19 21:07 UTC (permalink / raw)
  To: Thomas Graf, Jesse Gross, pshelar-l0M0P4e3n4LQT0dZR+AlfA,
	dev-yBygre7rU0TnMu66kgdUjQ
  Cc: netfilter-u79uwXL29TY76Z2rM5mHXA, Miklos Szeredi,
	kvm-u79uwXL29TY76Z2rM5mHXA, Michael S. Tsirkin, Jason Wang,
	Eric Dumazet, Jan Beulich, Tom Herbert, Herbert Xu,
	coreteam-Cap9r6Oaw4JrovVCs/uTlw, Jozsef Kadlecsik,
	xen-devel-GuqFBffKawtpuQazS67q72D2FQJk+8+b, Pablo Neira Ayuso,
	Jiri Pirko, Paul Durrant, netdev-u79uwXL29TY76Z2rM5mHXA,
	Florian Westphal, linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	David S. Miller, Daniel Borkmann,
	netfilter-devel-u79uwXL29TY76Z2rM5mHXA, Joe Perches,
	Patrick McHardy

On 19/03/14 20:47, Thomas Graf wrote:
> On 03/19/2014 09:38 PM, Zoltan Kiss wrote:
>> skb_zerocopy can copy elements of the frags array between skbs, but it
>> doesn't
>> orphan them. Also, it doesn't handle errors, so this patch takes care
>> of that
>> as well.
>>
>> Signed-off-by: Zoltan Kiss <zoltan.kiss-Sxgqhf6Nn4DQT0dZR+AlfA@public.gmane.org>
>> ---
>
>> +    if (unlikely(skb_orphan_frags(to, GFP_ATOMIC))) {
>> +        skb_tx_error(to);
>> +        return -ENOMEM;
>>       }
>
> I think you should move this down to right before we iterate over the
> frags.

I agree, I was mislead by that __skb_fill_page_desc, but now I see it is 
actually the head buffer of the source, not a frag from there. And in 
case of a failure in skb_copy_bits we can spare an orphan_frag.

Zoli

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

end of thread, other threads:[~2014-03-19 21:07 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-03-19 20:38 [PATCH] core, nfqueue, openvswitch: Orphan frags in skb_zerocopy and handle errors Zoltan Kiss
     [not found] ` <1395261516-305-1-git-send-email-zoltan.kiss-Sxgqhf6Nn4DQT0dZR+AlfA@public.gmane.org>
2014-03-19 20:47   ` Thomas Graf
     [not found]     ` <532A026E.5070609-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>
2014-03-19 21:07       ` Zoltan Kiss
  -- strict thread matches above, loose matches on Subject: below --
2014-03-18 21:17 Zoltan Kiss
     [not found] ` <1395177455-2077-1-git-send-email-zoltan.kiss-Sxgqhf6Nn4DQT0dZR+AlfA@public.gmane.org>
2014-03-19 20:24   ` David Miller
2014-03-19 20:39     ` Zoltan Kiss

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