From 1d8877c3c3ccab83c8509f0eac4ebe6605c6e34d Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Tue, 25 Mar 2014 16:55:44 +0000 Subject: [PATCH] nfqueue: Orphan frags in nfqnl_zcopy() and handle errors (CVE-2014-2568) svn path=/dists/sid/linux/; revision=21190 --- debian/changelog | 1 + ...gs-in-skb_zerocopy-and-handle-errors.patch | 105 ++++++++++++++++++ debian/patches/series | 1 + 3 files changed, 107 insertions(+) create mode 100644 debian/patches/bugfix/all/net-core-nfqueue-openvswitch-Orphan-frags-in-skb_zerocopy-and-handle-errors.patch diff --git a/debian/changelog b/debian/changelog index 1d00d1702..9b627a617 100644 --- a/debian/changelog +++ b/debian/changelog @@ -58,6 +58,7 @@ linux (3.13.7-1) UNRELEASED; urgency=medium [ Ben Hutchings ] * [arm] mm: Avoid ABI change in 3.13.6 (fixes FTBFS) + * nfqueue: Orphan frags in nfqnl_zcopy() and handle errors (CVE-2014-2568) -- Ben Hutchings Fri, 21 Mar 2014 19:47:01 +0000 diff --git a/debian/patches/bugfix/all/net-core-nfqueue-openvswitch-Orphan-frags-in-skb_zerocopy-and-handle-errors.patch b/debian/patches/bugfix/all/net-core-nfqueue-openvswitch-Orphan-frags-in-skb_zerocopy-and-handle-errors.patch new file mode 100644 index 000000000..1056f282d --- /dev/null +++ b/debian/patches/bugfix/all/net-core-nfqueue-openvswitch-Orphan-frags-in-skb_zerocopy-and-handle-errors.patch @@ -0,0 +1,105 @@ +Subject: [v4] core, nfqueue, openvswitch: Orphan frags in skb_zerocopy and handle errors +From: Zoltan Kiss +Date: Fri, 21 Mar 2014 10:31:34 +0000 +Origin: https://patchwork.ozlabs.org/patch/332544/ + +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 +Acked-by: Thomas Graf +[bwh: 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.] +--- +--- a/net/netfilter/nfnetlink_queue_core.c ++++ b/net/netfilter/nfnetlink_queue_core.c +@@ -235,22 +235,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); +@@ -268,6 +269,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; +@@ -278,6 +284,8 @@ nfqnl_zcopy(struct sk_buff *to, const st + j++; + } + skb_shinfo(to)->nr_frags = j; ++ ++ return 0; + } + + static int +@@ -374,13 +382,16 @@ nfqnl_build_packet_message(struct net *n + + skb = nfnetlink_alloc_skb(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; + } +@@ -504,13 +515,15 @@ nfqnl_build_packet_message(struct net *n + 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; diff --git a/debian/patches/series b/debian/patches/series index 21d77afcb..fd62e6a4d 100644 --- a/debian/patches/series +++ b/debian/patches/series @@ -93,3 +93,4 @@ debian/netdev-avoid-abi-change-in-3.13.6.patch debian/can-avoid-abi-change-in-3.13.6.patch debian/arm-mm-avoid-abi-change-in-3.13.6.patch debian/fireware-avoid-abi-change-in-3.13.7.patch +bugfix/all/net-core-nfqueue-openvswitch-Orphan-frags-in-skb_zerocopy-and-handle-errors.patch