--- /dev/null
+From 36d5fe6a000790f56039afe26834265db0a3ad4c Mon Sep 17 00:00:00 2001
+From: Zoltan Kiss <zoltan.kiss@citrix.com>
+Date: Wed, 26 Mar 2014 22:37:45 +0000
+Subject: core, nfqueue, openvswitch: Orphan frags in skb_zerocopy and handle errors
+
+From: Zoltan Kiss <zoltan.kiss@citrix.com>
+
+commit 36d5fe6a000790f56039afe26834265db0a3ad4c upstream.
+
+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, and modify the callers accordingly. skb_tx_error() is also added to
+the callers so they will signal the failed delivery towards the creator of the
+skb.
+
+Signed-off-by: Zoltan Kiss <zoltan.kiss@citrix.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+[bwh: Backported to 3.13: skb_zerocopy() is new in 3.14, but was moved from a
+ static function in nfnetlink_queue. We need to patch that and its caller, but
+ not openvswitch.]
+Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+---
+ net/netfilter/nfnetlink_queue_core.c | 29 +++++++++++++++++++++--------
+ 1 file changed, 21 insertions(+), 8 deletions(-)
+
+--- a/net/netfilter/nfnetlink_queue_core.c
++++ b/net/netfilter/nfnetlink_queue_core.c
+@@ -227,22 +227,23 @@ nfqnl_flush(struct nfqnl_instance *queue
+ spin_unlock_bh(&queue->lock);
+ }
+
+-static void
++static int
+ nfqnl_zcopy(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;
+
+ /* 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 (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);
+@@ -260,6 +261,11 @@ nfqnl_zcopy(struct sk_buff *to, const st
+ to->len += len + plen;
+ to->data_len += len + plen;
+
++ if (unlikely(skb_orphan_frags(from, GFP_ATOMIC))) {
++ skb_tx_error(from);
++ return -ENOMEM;
++ }
++
+ for (i = 0; i < skb_shinfo(from)->nr_frags; i++) {
+ if (!len)
+ break;
+@@ -270,6 +276,8 @@ nfqnl_zcopy(struct sk_buff *to, const st
+ j++;
+ }
+ skb_shinfo(to)->nr_frags = j;
++
++ return 0;
+ }
+
+ static int nfqnl_put_packet_info(struct sk_buff *nlskb, struct sk_buff *packet)
+@@ -355,13 +363,16 @@ nfqnl_build_packet_message(struct nfqnl_
+
+ skb = nfnetlink_alloc_skb(&init_net, size, queue->peer_portid,
+ GFP_ATOMIC);
+- if (!skb)
++ if (!skb) {
++ skb_tx_error(entskb);
+ return NULL;
++ }
+
+ nlh = nlmsg_put(skb, 0, 0,
+ NFNL_SUBSYS_QUEUE << 8 | NFQNL_MSG_PACKET,
+ sizeof(struct nfgenmsg), 0);
+ if (!nlh) {
++ skb_tx_error(entskb);
+ kfree_skb(skb);
+ return NULL;
+ }
+@@ -481,13 +492,15 @@ nfqnl_build_packet_message(struct nfqnl_
+ nla->nla_type = NFQA_PAYLOAD;
+ nla->nla_len = nla_attr_size(data_len);
+
+- nfqnl_zcopy(skb, entskb, data_len, hlen);
++ if (nfqnl_zcopy(skb, entskb, data_len, hlen))
++ goto nla_put_failure;
+ }
+
+ nlh->nlmsg_len = skb->len;
+ return skb;
+
+ nla_put_failure:
++ skb_tx_error(entskb);
+ kfree_skb(skb);
+ net_err_ratelimited("nf_queue: error creating packet message\n");
+ return NULL;