From 20ac8e7c1a0e99dfd57ffe486093c92328c9edbe Mon Sep 17 00:00:00 2001 From: Josh Boyer Date: Mar 28 2014 15:05:54 +0000 Subject: CVE-2014-2568 net: potential info leak when ubuf backed skbs are zero copied (rhbz 1079012 1079013) --- diff --git a/kernel.spec b/kernel.spec index f4870a4..8e24564 100644 --- a/kernel.spec +++ b/kernel.spec @@ -787,6 +787,9 @@ Patch25045: netfilter-nf_conntrack_dccp-fix-skb_header_pointer-A.patch #CVE-2014-0131 rhbz 1074589 1079006 Patch25048: skbuff-zero-copy.patch +#CVE-2014-2568 rhbz 1079012 1079013 +Patch25049: nfqueue-Orphan-frags-in-nfqnl_zcopy-and-handle-error.patch + # END OF PATCH DEFINITIONS %endif @@ -1530,6 +1533,9 @@ ApplyPatch netfilter-nf_conntrack_dccp-fix-skb_header_pointer-A.patch #CVE-2014-0131 rhbz 1074589 1079006 ApplyPatch skbuff-zero-copy.patch +#CVE-2014-2568 rhbz 1079012 1079013 +ApplyPatch nfqueue-Orphan-frags-in-nfqnl_zcopy-and-handle-error.patch + # END OF PATCH APPLICATIONS %endif @@ -2341,6 +2347,9 @@ fi # ||----w | # || || %changelog +* Fri Mar 28 2014 Josh Boyer +- CVE-2014-2568 net: potential info leak when ubuf backed skbs are zero copied (rhbz 1079012 1079013) + * Mon Mar 24 2014 Justin M. Forbes - 3.13.7-200 - Linux v3.13.7 diff --git a/nfqueue-Orphan-frags-in-nfqnl_zcopy-and-handle-error.patch b/nfqueue-Orphan-frags-in-nfqnl_zcopy-and-handle-error.patch new file mode 100644 index 0000000..107b724 --- /dev/null +++ b/nfqueue-Orphan-frags-in-nfqnl_zcopy-and-handle-error.patch @@ -0,0 +1,117 @@ +Bugzilla: 1079013 +Upstream-status: Queued in netdev tree, backport for 3.13.y sent + +From 93f7cfcac69051641d5b10325164a0f313ef5185 Mon Sep 17 00:00:00 2001 +From: Josh Boyer +Date: Fri, 28 Mar 2014 09:32:19 -0400 +Subject: [PATCH] nfqueue: Orphan frags in nfqnl_zcopy and handle errors + +Backport of upstream commit 36d5fe6a0007 to 3.13.y + +nfqnl_zcopy 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 caller 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 +Signed-off-by: David S. Miller +Signed-off-by: Josh Boyer +--- + net/netfilter/nfnetlink_queue_core.c | 31 ++++++++++++++++++++++--------- + 1 file changed, 22 insertions(+), 9 deletions(-) + +diff --git a/net/netfilter/nfnetlink_queue_core.c b/net/netfilter/nfnetlink_queue_core.c +index 21258cf..b241654 100644 +--- a/net/netfilter/nfnetlink_queue_core.c ++++ b/net/netfilter/nfnetlink_queue_core.c +@@ -235,22 +235,23 @@ nfqnl_flush(struct nfqnl_instance *queue, nfqnl_cmpfn cmpfn, unsigned long data) + spin_unlock_bh(&queue->lock); + } + +-static void +-nfqnl_zcopy(struct sk_buff *to, const struct sk_buff *from, int len, int hlen) ++static int ++nfqnl_zcopy(struct sk_buff *to, 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 struct sk_buff *from, int len, int hlen) + 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 struct sk_buff *from, int len, int hlen) + j++; + } + skb_shinfo(to)->nr_frags = j; ++ ++ return 0; + } + + static int +@@ -374,13 +382,16 @@ nfqnl_build_packet_message(struct net *net, struct nfqnl_instance *queue, + + 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 *net, struct nfqnl_instance *queue, + 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; +-- +1.8.5.3 +